Skip to content

ドメイン固有言語(DSL):バックエンドの世界における「コードらしくないコード」

はじめに

ある実際の事例では、エンジニアの Armin が新しい会社で AI を使って約 4 万行のコード(Go + YAML + Pulumi + SDK グルーコード)からなるインフラサービスを構築し、その 90% 以上が AI によって生成されました。この事例には、YAML、Pulumi、HCL、Lua、SDK グルーコードなど、初心者には馴染みのない用語が数多く登場します。これらは Python でも JavaScript でもありませんが、バックエンドプロジェクトでは至る所で使われています。本記事では、ドメイン固有言語(DSL) という統一的な視点から、これらの技術を体系的に紹介します。

本記事の学習目標

バックエンド開発では、汎用プログラミング言語(Python、Go、Java など)で書かれたビジネスロジックに加えて、用途も文法も異なるが、いずれも汎用プログラミング言語ではないファイルやコードが大量に存在します。それらには共通の上位概念があります:DSL(Domain-Specific Language、ドメイン固有言語) です。

本記事を読み終えると、以下のことができるようになります:

  • DSL と汎用プログラミング言語(GPL)の本質的な違いを理解する
  • DSL の分類体系(データシリアライゼーション形式、組み込みスクリプト言語、インフラストラクチャ定義言語)を把握する
  • XML、JSON、YAML、TOML、CSV、Protobuf などのデータ形式の適用シーンを区別する
  • Lua などの組み込みスクリプト言語の設計目的を理解する
  • Terraform(HCL)と Pulumi の原理と違いを説明する
  • OpenAPI 仕様と SDK 自動生成の仕組みを理解する
  • どのような種類のコードが AI による生成に適しているかを判断する
テーマコアコンセプト
第 1 章DSL 総論DSL と GPL の定義、分類体系と全景図
第 2 章データシリアライゼーション形式XML、JSON、YAML、TOML、CSV、Protobuf など
第 3 章組み込みスクリプト言語Lua などの言語の設計哲学と典型的な応用
第 4 章Infrastructure as CodeTerraform(HCL)、Pulumi の原理と比較
第 5 章グルーコードと SDK 生成OpenAPI 仕様とクライアントコードの自動生成
第 6 章AI と DSL の関係AI が DSL コードの生成を特に得意とする理由

1. DSL 総論:汎用言語の外側にあるもう一つの世界

1.1 DSL とは?

DSL(Domain-Specific Language、ドメイン固有言語) は、特定の領域や特定のタスクのために設計された言語です。対になる概念として GPL(General-Purpose Language、汎用プログラミング言語) があり、Python、Java、Go、C++ などが該当します。これらは任意の計算問題を解決できるように設計されています。

両者の本質的な違い:

次元GPL(汎用プログラミング言語)DSL(ドメイン固有言語)
設計目標任意の計算問題を解決する特定の領域の問題を解決する
表現範囲チューリング完全、理論上あらゆる計算が可能通常、意図的に表現範囲が制限されている
学習コスト高め、完全な言語体系の理解が必要低め、その領域の概念を理解すればよい
代表例Python、Java、Go、C++、JavaScriptSQL、HTML/CSS、正規表現、YAML、HCL

実はあなたはすでに DSL を使っています:

  • SQL はデータベースクエリ領域の DSL です——SELECT * FROM users WHERE age > 18 でデータを検索し、Python で走査ロジックを手書きしたりしません
  • HTML/CSS は Web ページの構造とスタイル領域の DSL です——タグと属性でページを記述し、C++ でピクセル操作をしたりしません
  • 正規表現 はテキストパターンマッチング領域の DSL です——\d{3}-\d{4} で電話番号にマッチさせ、文字比較ループを手書きしたりしません

1.2 DSL の分類

DSL は「チューリング完全性を持つかどうか」によって大きく 2 つに分類できます:

外部 DSL(External DSL)

独立した文法とパーサーを持ち、特定の汎用プログラミング言語に依存しません。ユーザーが書いたコードは専用のインタプリタやコンパイラによって処理されます。

  • 純粋データ記述型:JSON、YAML、XML、TOML、CSV、Protobuf(ロジックを一切含まない)
  • クエリ/操作型:SQL、GraphQL、正規表現(限定的なロジック能力を持つ)
  • ドメインモデリング型:HCL(Terraform)、Dockerfile、Nginx 設定文法(特定領域の状態を宣言的に記述)

内部 DSL(Internal DSL / Embedded DSL)

特定の汎用プログラミング言語の内部に寄生し、ホスト言語の文法を利用してドメイン固有の表現方法を構築します。コード自体は合法的なホスト言語のコードですが、専用言語のように読めます。

  • Pulumi(TypeScript/Python/Go で記述するが、API は宣言的設定のように設計されている)
  • Ruby on Rails のルーティング定義(get '/users', to: 'users#index' は合法的な Ruby コードだが、設定のように読める)
  • テストフレームワークのアサーション文法(expect(value).toBe(42) は合法的な JavaScript だが、自然言語のように読める)

1.3 バックエンドプロジェクトにおける DSL の全景図

典型的なバックエンドプロジェクトでは、以下のような DSL に遭遇します:

バックエンドプロジェクトにおける DSL
├── データシリアライゼーション形式(データ構造を記述)
│   ├── テキスト形式:JSON、YAML、XML、TOML、CSV、INI
│   └── バイナリ形式:Protobuf、MessagePack、Avro、BSON
├── 組み込みスクリプト言語(プログラマブルな設定層)
│   ├── Lua(ゲームエンジン、Nginx、Redis)
│   ├── GDScript(Godot エンジン)
│   └── Jsonnet(設定テンプレート生成)
├── インフラストラクチャ・運用 DSL(システム状態を宣言的に記述)
│   ├── HCL(Terraform)
│   ├── Dockerfile / Docker Compose YAML
│   └── Nginx / Apache 設定文法
└── インターフェース記述言語(API 契約を記述)
    ├── OpenAPI / Swagger
    ├── Protocol Buffers(.proto ファイル)
    └── GraphQL Schema

この全景図を理解した上で、以降の章では各ブランチを順に展開していきます。


2. データシリアライゼーション形式:テキストで構造化データを記述する

2.1 データシリアライゼーションとは?

シリアライゼーション(Serialization) とは、メモリ上のデータ構造(オブジェクト、辞書、配列など)を、保存や転送が可能なテキスト/バイトストリームに変換するプロセスです。逆に、テキスト/バイトストリームからメモリ上のデータ構造に復元することをデシリアライゼーション(Deserialization) と呼びます。

データシリアライゼーション形式は DSL の中で最も基本的なカテゴリです——これらは純粋データ記述型の外部 DSL に属し、ロジック能力を一切持たず、「値が何であるか」を静的に記述するだけです。

2.2 なぜこれらの形式が必要なのか?

あなたがバックエンドサービスを開発し、データベースアドレスが localhost:5432 だとします。このアドレスをソースコードにハードコードすると、ローカル開発では問題ありませんが、本番環境にデプロイする際にデータベースアドレスが db.prod.company.com:5432 に変わると、ソースコードを修正して再コンパイルする必要があります。

エンジニアリングの一般的なプラクティスは:可変パラメータをコードから分離し、独立した設定ファイルに格納することです。 プログラムは起動時に設定ファイルを読み取り、その値に基づいて動作を決定します。

設定以外にも、データシリアライゼーション形式は以下のような場面で広く使われています:システム間のデータ交換(API リクエスト/レスポンス)、データ永続化ストレージ、クロスランゲージ通信など。

2.3 人間が読めるテキスト形式

以下は、エンジニアリングで最も一般的なテキストシリアライゼーション形式を、歴史順に紹介します。

INI

最も初期の設定形式で、Windows システムに起源を持ちます。構造はシンプルで、セクション(section)とキー・バリューペアで構成されます:

ini
[database]
host = localhost
port = 5432

[server]
debug = true

可読性が高いのが利点です。制限として、ネスト構造や配列型をサポートしておらず、複雑な設定を表現できません。現在は主にレガシーシステムや一部の Linux 設定(php.inimy.cnf など)で見られます。

CSV

CSV(Comma-Separated Values、カンマ区切り値) は最もシンプルなテーブルデータ形式です:

csv
name,age,city
Alice,30,Beijing
Bob,25,Shanghai

各行が 1 レコードで、フィールドはカンマで区切られます。CSV はデータのインポート/エクスポート、スプレッドシート交換、データ分析パイプラインで広く使われています。制限として、フラットな 2 次元テーブルしか表現できず、ネスト構造をサポートせず、型情報もありません(すべての値は文字列です)。

XML

XML(eXtensible Markup Language、拡張マークアップ言語) は 1998 年に誕生し、かつてはデータ交換の主流標準でした:

xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
  <database>
    <host>localhost</host>
    <port>5432</port>
  </database>
  <server>
    <debug>true</debug>
    <allowed_origins>
      <origin>https://example.com</origin>
      <origin>https://app.example.com</origin>
    </allowed_origins>
  </server>
</config>

XML の表現力は非常に高く、ネスト、属性、名前空間、Schema 検証などの高度な機能をサポートしています。しかし文法が冗長で——大量の開始/終了タグによりシグナル/ノイズ比が低く、手動での作成や読み取りの体験は良くありません。

XML は以下の分野で今も広く使われています:

  • Java エコシステム(Maven の pom.xml、Spring 設定、Android レイアウトファイル)
  • エンタープライズ Web サービス(SOAP プロトコル)
  • オフィス文書形式(.docx.xlsx は実質 ZIP 圧縮された XML ファイルの集合体)
  • RSS/Atom フィード、SVG ベクターグラフィックス

JSON

JSON(JavaScript Object Notation) は 2001 年に誕生し、その簡潔さから XML に代わって Web API データ交換のデファクトスタンダードとなりました:

json
{
  "database": {
    "host": "localhost",
    "port": 5432
  },
  "server": {
    "debug": true
  }
}

構造が明確で、ほぼすべてのプログラミング言語がネイティブ解析をサポートしているのが利点です。主な欠点はコメントをサポートしていないことと、大量の括弧や引用符により手動編集時にミスが発生しやすいことです。JSON はフロントエンドプロジェクトの設定標準形式(package.jsontsconfig.json)でもあります。

YAML

YAML(YAML Ain't Markup Language) も 2001 年に誕生し、現在バックエンドと DevOps 分野で最も広く使われている設定形式です。Docker Compose、Kubernetes、GitHub Actions などのツールが YAML を採用しています:

yaml
# データベース設定
database:
  host: localhost
  port: 5432

# サーバー設定
server:
  debug: true
  allowed_origins:
    - https://example.com
    - https://app.example.com

コメントをサポートし、文法が簡潔で、複雑なネスト構造を表現できるのが利点です。欠点はインデントに依存して階層関係を表現することで、インデントの誤りが解析失敗につながります。これは初心者が最も頻繁に遭遇する問題です。

補足:YAML の正式名称 "YAML Ain't Markup Language" は再帰的頭字語です。

TOML

TOML(Tom's Obvious Minimal Language) は 2013 年に誕生し、Rust のパッケージマネージャ Cargo や Python の pyproject.toml で採用されています:

toml
[database]
host = "localhost"
port = 5432

[server]
debug = true
allowed_origins = [
  "https://example.com",
  "https://app.example.com"
]

TOML は INI の簡潔さと YAML の表現力を両立させつつ、インデント依存がもたらす問題を回避しようとしています。

2.4 バイナリシリアライゼーション形式

上記の形式はいずれも人間が読めるテキストです。パフォーマンスとサイズにより高い要件があるシーンでは、バイナリシリアライゼーション形式という別のカテゴリが存在します——可読性を犠牲にして、より小さなサイズとより高速な解析速度を得ます。

形式開発元特徴典型的な使用シーン
Protocol Buffers (Protobuf)Google事前定義の .proto Schema ファイルが必要、強い型付け、非常に小さいサイズgRPC 通信、Google 内部サービス、高パフォーマンスマイクロサービス
MessagePackコミュニティJSON に似たバイナリ版、Schema 不要Redis 内部エンコーディング、クロスランゲージ高パフォーマンス通信
AvroApacheSchema 進化をサポート、ビッグデータシーンに適するHadoop / Kafka エコシステムのデータシリアライゼーション
BSONMongoDBJSON のバイナリ拡張、より多くのデータ型をサポートMongoDB データベース内部ストレージ形式

Protocol Buffers を例にとると、まず Schema を定義する必要があります:

protobuf
// user.proto
syntax = "proto3";

message User {
  string name = 1;
  int32 age = 2;
  string email = 3;
}

その後、コンパイラ(protoc)を通じて各言語のシリアライゼーション/デシリアライゼーションコードが自動生成されます。この「まず Schema を定義し、次にコードを生成する」パターンは、後述する OpenAPI SDK 生成の考え方と一致しています。

2.5 完全比較

形式タイプ誕生年代可読性コメント対応典型的な使用シーン
INIテキスト1980sシステム設定、レガシープロジェクト
CSVテキスト1972データインポート/エクスポート、テーブル交換
XMLテキスト1998Java エコシステム、エンタープライズ Web サービス、文書形式
JSONテキスト2001Web API データ交換、フロントエンド設定
YAMLテキスト2001Docker、K8s、CI/CD、バックエンドサービス設定
TOMLテキスト2013Rust / Python プロジェクト設定
Protobufバイナリ2008なしgRPC、高パフォーマンスマイクロサービス通信
MessagePackバイナリ2008なし高パフォーマンスクロスランゲージ通信
Avroバイナリ2009なしHadoop / Kafka ビッグデータパイプライン
BSONバイナリ2009なしMongoDB 内部ストレージ

ポイント:これらすべての形式の本質的な機能は同じです——構造化データを保存・転送可能な形式に変換すること。テキスト形式は人間の可読性と編集のしやすさを優先し、バイナリ形式は解析パフォーマンスと転送サイズを優先します。どの形式を選ぶかは、具体的なシーンの要件トレードオフによって決まります。


3. 組み込みスクリプト言語:プログラマブルな設定層

3.1 概念定義

Python、JavaScript、Go などの言語は汎用プログラミング言語(General-Purpose Language)であり、独立して実行でき、完全なアプリケーションを構築できます。

これとは異なり、他のホストプログラムに組み込まれて実行されるよう特別に設計された言語があります。これらはホストプログラムにプログラマブルな拡張機能を提供します。このような言語を組み込みスクリプト言語(Embedded Scripting Language) と呼びます。

これらが解決する核心的な問題は:静的設定ファイル(YAML/JSON)の表現力では不十分で、条件分岐やループなどのロジックを導入する必要がある場合に、ホストプログラムのソースコードを変更せずに動的な振る舞いを実現する方法です。

3.2 Lua:最も代表的な組み込みスクリプト言語

Lua(ポルトガル語で「月」の意味)は非常に軽量なスクリプト言語で、インタプリタ全体をコンパイルしてもわずか数百 KB です。その設計目標は独立して実行することではなく、組み込み可能な拡張層として機能することです。

Lua の典型的な応用シーン:

  • ゲームエンジン:『World of Warcraft』のアドオンシステム、『Roblox』のゲームスクリプトはいずれも Lua を使用しています。ゲームエンジンは C/C++ でコアレンダリングと物理計算を実装し、レベルロジックや NPC ダイアログなど頻繁に変更される部分を Lua スクリプトに任せます。これにより、プランナーがゲーム内容を変更する際にエンジンを再コンパイルする必要がありません。

  • Web サーバー:OpenResty は Lua を Nginx 内部に組み込み、運用者が Lua スクリプトでリクエストフィルタリング、レート制限、認証などのロジックを実装できるようにします。Nginx の C ソースコードを変更する必要はありません。

  • データベース:Redis は Lua スクリプトをサーバーサイドに送信して実行することをサポートしており、アトミック性が保証される必要がある複合操作(「読み取り後書き込み」など)の実装に使用されます。

以下は Nginx(OpenResty)に組み込まれた Lua スクリプトの例です:

lua
-- 機能:/api/secret パスに対してトークン認証を行う
local uri = ngx.var.uri
local token = ngx.req.get_headers()["Authorization"]

if uri == "/api/secret" and token ~= "Bearer my-secret-token" then
    ngx.status = 403
    ngx.say("Access denied")
    return ngx.exit(403)
end

3.3 その他の組み込みスクリプト言語

言語ホスト環境典型的な用途
Luaゲームエンジン、Nginx(OpenResty)、Redisゲームロジック、ゲートウェイポリシー、キャッシュ操作
VimScript / LuaVim / Neovim エディタエディタプラグイン開発
Emacs LispEmacs エディタエディタ動作のカスタマイズ
GDScriptGodot ゲームエンジンゲームロジックスクリプト
JsonnetKubernetes エコシステム / 設定生成ツール大量の類似 JSON/YAML 設定のテンプレート化生成

ポイント:組み込みスクリプト言語は DSL 分類において内部 DSL と外部 DSL の境界領域に位置します——これらは独立した言語(独自の文法とインタプリタを持つ)ですが、設計目標は独立したアプリケーション構築ではなく、ホストプログラムに組み込まれて実行されることです。これらは「静的設定ファイル」(純粋データ記述型 DSL)と「汎用プログラミング言語」(GPL)の間のギャップを埋めます:設定がロジック(条件分岐、ループ、関数呼び出し)を表現する必要がある場合に、軽量スクリプト言語を組み込むことがエンジニアリング上の標準的な解決策です。


4. Infrastructure as Code(コードとしてのインフラストラクチャ)

4.1 「インフラストラクチャ」とは

バックエンドエンジニアリングにおいて、「インフラストラクチャ(Infrastructure)」とはアプリケーションの実行が依存する基盤リソースを指します:

  • コンピューティングリソース:サーバー(仮想マシンまたはコンテナ)
  • データストレージ:データベースインスタンス、オブジェクトストレージバケット
  • ネットワーク:ファイアウォールルール、ロードバランサー、DNS 設定
  • ミドルウェア:メッセージキュー、キャッシュクラスター

クラウドコンピューティング時代において、これらのリソースはクラウドサービスプロバイダー(AWS、Alibaba Cloud、Tencent Cloud など)のコンソールを通じて GUI で作成・管理されます。

4.2 手動管理の限界

コンソールを使った手動操作は小規模プロジェクトでは実行可能ですが、プロジェクト規模が拡大するにつれて、以下の問題が露呈します:

  1. 再現不可能:操作手順が記録されず、同一環境を正確に再現できない
  2. 監査不可能:「誰がいつどの設定を変更したか」を追跡できない
  3. コラボレーション不可能:操作プロセスをバージョン管理に組み込めず、コードレビューができない
  4. ミスが発生しやすい:本番環境での手動操作には誤操作のリスクがある

Infrastructure as Code(IaC) の核心的な考え方は:コードを使ってインフラストラクチャリソースを宣言的に定義し、バージョン管理、自動実行、再現可能なデプロイを実現することです。

4.3 Terraform

Terraform は現在最も広く使われている IaC ツールで、HashiCorp 社によって開発されました。専用の HCL(HashiCorp Configuration Language) 言語を使用します。

Terraform は宣言的パラダイムを採用しています:ユーザーが望ましい最終状態を記述すると、Terraform が現在の状態から目標状態に到達するために必要な操作を自動的に計算します。

hcl
# クラウドサーバーを 1 台定義
resource "aws_instance" "my_server" {
  ami           = "ami-0c55b159cbfafe1f0"  # OS イメージ
  instance_type = "t3.micro"               # インスタンスタイプ

  tags = {
    Name = "my-first-server"
  }
}

# PostgreSQL データベースインスタンスを定義
resource "aws_db_instance" "my_database" {
  engine         = "postgres"
  instance_class = "db.t3.micro"
  username       = "admin"
  password       = "please-use-secrets-manager"
}

実行フロー:

bash
terraform plan    # 実行予定の変更をプレビュー
terraform apply   # 確認して実行、クラウドプラットフォームにリソースを自動作成

4.4 Pulumi

Pulumi は別のアプローチを提供します:専用の HCL 文法を学ぶ代わりに、汎用プログラミング言語(TypeScript、Python、Go など)を直接使ってインフラストラクチャを定義するというものです。

同じサーバー定義を Pulumi + TypeScript で表現すると:

typescript
import * as aws from "@pulumi/aws";

const server = new aws.ec2.Instance("my-server", {
    ami: "ami-0c55b159cbfafe1f0",
    instanceType: "t3.micro",
    tags: { Name: "my-first-server" },
});

const bucket = new aws.s3.Bucket("my-bucket", {
    acl: "private",
});

export const serverIp = server.publicIp;

汎用プログラミング言語を使用しているため、開発者はループ、条件分岐、関数抽象などの言語機能を活用して複雑なインフラストラクチャロジックを処理できます。

4.5 Terraform と Pulumi の比較

次元TerraformPulumi
言語HCL(専用言語)TypeScript / Python / Go などの汎用言語
学習コストHCL 文法を学ぶ必要がある既に習得済みのプログラミング言語を使用、学習コストが低い
コミュニティエコシステム非常に成熟、ほぼすべてのクラウドサービスプロバイダーをカバー急速に成長中だが、規模は Terraform より小さい
適用シーン運用チーム主導の標準化されたインフラ管理開発者主導のプロジェクト、複雑なロジックが必要なシーン
AI コード生成適性高い(パターンが固定的)非常に高い(本質的に汎用プログラミング言語のコード)

ポイント:IaC ツールにおける HCL は典型的な外部 DSL です——独立した文法とパーサーを持ち、インフラストラクチャの状態を宣言的に記述することに特化しています。一方 Pulumi は内部 DSL 戦略を採用しています——汎用プログラミング言語の文法を使ってドメイン固有の概念を表現します。両者の目標は同じで(インフラ管理を手動操作からコード駆動に変える)、手段が異なります(専用言語 vs 汎用言語)。コードは Git バージョン管理に組み入れ、チームレビューを行い、自動実行とロールバックが可能です。


5. グルーコードと SDK 自動生成

5.1 グルーコードとは

ソフトウェアエンジニアリングにおいて、グルーコード(Glue Code) とは、それ自体はビジネスロジックを含まず、2 つのシステムやモジュールを接続するためだけに存在するコードを指します。

典型的なグルーコードには以下が含まれます:

  • フロントエンドがバックエンド API を呼び出す際に書く HTTP リクエストコード(URL 組み立て、リクエストヘッダー設定、レスポンス解析)
  • バックエンドサービス A がサービス B のインターフェースを呼び出す際に書く HTTP クライアントコード
  • 異なるプログラミング言語間のインターフェースアダプターコード

この種のコードの特徴は:高度に反復的で、パターンが固定的だが、省略できないことです。

5.2 OpenAPI 仕様とコード自動生成

グルーコードが高度にパターン化された特徴を持つ以上、エンジニアリングの世界での解決策は:まず標準形式で API インターフェースを記述し、次にツールでクライアントコードを自動生成することです。

OpenAPI 仕様(旧称 Swagger)は REST API を記述する業界標準です。YAML または JSON 形式を使用し、API のパス、パラメータ、リクエストボディ、レスポンス構造を正確に定義します:

yaml
openapi: 3.0.0
info:
  title: メールサービス API
  version: 1.0.0

paths:
  /emails:
    post:
      summary: メール送信
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                  example: "user@example.com"
                subject:
                  type: string
                body:
                  type: string
      responses:
        '200':
          description: 送信成功

この仕様ファイルに基づいて、openapi-generator などのツールを使うと、複数言語のクライアント SDK を自動生成できます:

  • Pythonclient.emails.send(to="user@example.com", subject="Hi", body="Hello")
  • TypeScriptclient.emails.send({ to: "user@example.com", subject: "Hi", body: "Hello" })
  • Goclient.Emails.Send(ctx, &SendEmailRequest{To: "user@example.com", ...})

生成された SDK は HTTP リクエストのすべての詳細をカプセル化し、呼び出し側は URL パス、リクエストメソッド、シリアライゼーション形式などの低レイヤ実装を気にする必要がありません。

5.3 Armin の事例を再解釈する

本記事の冒頭の事例に戻ると、各構成要素を正確に理解できるようになりました:

構成要素性質説明
Goビジネスロジックコードメール送受信サービスのコア機能実装
YAML設定ファイルサービス設定、CI/CD パイプライン定義、OpenAPI 仕様ファイル
PulumiインフラストラクチャコードGo/TypeScript でクラウドリソース(サーバー、データベース、ネットワーク)を定義
SDK グルーコード自動生成されたクライアントライブラリOpenAPI 仕様から自動生成された Python および TypeScript SDK

このうち YAML 設定、Pulumi リソース定義、SDK グルーコードの 3 つはいずれも高度にパターン化され、明確な仕様制約があるコードであり、これこそが AI コード生成能力が最も強い領域です。したがって「4 万行のコードのうち 90% が AI によって生成された」というのは合理的です。


6. AI と DSL の関係

6.1 AI コード生成の適用性分析

特徴次元AI 生成に適するAI 生成に適さない
パターン化の度合い高度に反復的、固定テンプレートが存在する創造的な設計が必要、前例がない
仕様制約明確な schema や文法仕様がある要件が曖昧で、境界が不明確
コンテキスト依存局所的に自己完結、単一の定義がグローバルな理解に依存しないシステム全体のアーキテクチャ意図を理解する必要がある
検証可能性ツールによる自動検証が可能(例:terraform validate設計の妥当性を人手で判断するしかない

本記事で紹介した 4 種類の技術——設定ファイル、組み込みスクリプト、IaC コード、SDK グルーコード——はいずれも左列の特徴を備えています。これが、AI がこれらの領域でビジネスロジックコードよりも顕著に優れたコード生成効果を発揮する理由です。

6.2 評価フレームワーク

あるコードが AI による生成に適しているかを判断する際、以下の 3 つの基準を参考にできます:

  1. 既存の仕様や schema が存在するか? —— 存在すれば AI フレンドリー
  2. 大量に繰り返されるパターンか? —— そうであれば AI フレンドリー
  3. 生成結果をツールで自動検証できるか? —— できれば AI フレンドリー

3 項目すべてを満たすコード(OpenAPI 仕様からの SDK 生成、Terraform での同型リソースの一括定義など)は、AI 生成に大きく依存できます。3 項目すべてを満たさないコード(新しい分散合意プロトコルの設計など)は、依然としてエンジニアが自ら完成させる必要があります。


7. 用語集

用語正式名称 / 日本語定義
DSLDomain-Specific Language / ドメイン固有言語特定の領域向けに設計された言語、汎用プログラミング言語と対になる
GPLGeneral-Purpose Language / 汎用プログラミング言語任意の計算問題を解決できるプログラミング言語、Python、Java、Go など
外部 DSLExternal DSL独立した文法とパーサーを持つドメイン固有言語、SQL、HCL、YAML など
内部 DSLInternal DSL / Embedded DSL汎用プログラミング言語内部に寄生し、ホスト文法を利用して構築されたドメイン固有表現、Pulumi など
データシリアライゼーションData Serializationメモリ上のデータ構造を保存または転送可能な形式に変換するプロセス
INIInitialization最も初期のキー・バリュー設定形式、Windows システムに起源
CSVComma-Separated Values / カンマ区切り値カンマでフィールドを区切るプレーンテキストテーブル形式
XMLeXtensible Markup Language / 拡張マークアップ言語タグベースのテキストデータ形式、表現力が高いが文法が冗長
JSONJavaScript Object Notationキー・バリューベースの軽量データ交換形式、Web API のデファクトスタンダード
YAMLYAML Ain't Markup Languageインデントベースの設定ファイル形式、バックエンドと DevOps 分野で広く使用
TOMLTom's Obvious Minimal Language明示的な文法の設定形式、Rust と Python エコシステムでよく使われる
ProtobufProtocol BuffersGoogle 開発のバイナリシリアライゼーション形式、Schema の事前定義が必要、サイズが小さく高速
MessagePackJSON に似たバイナリシリアライゼーション形式、Schema 不要
Lua軽量組み込みスクリプト言語、ゲームエンジン、Web サーバー、データベース拡張でよく使われる
IaCInfrastructure as Code / コードとしてのインフラストラクチャコードでクラウドコンピューティングリソースを定義・管理するエンジニアリングプラクティス
TerraformHashiCorp 開発の IaC ツール、HCL 宣言型言語を使用
HCLHashiCorp Configuration LanguageTerraform が使用する専用設定言語
Pulumi汎用プログラミング言語をサポートする IaC ツール
OpenAPIREST API インターフェースを記述する業界標準仕様(旧称 Swagger)
SDKSoftware Development Kit / ソフトウェア開発キットAPI 呼び出しの詳細をカプセル化したクライアントライブラリ
グルーコードGlue Codeビジネスロジックを含まず、2 つのシステムを接続するためだけのアダプターコード

まとめ

バックエンドエンジニアリングには大量の非ビジネスロジックコードが存在します。それらには共通の上位概念があります:DSL(ドメイン固有言語)——特定の領域向けに設計された、汎用プログラミング言語と対になる言語です。

本記事で紹介した DSL は 4 つのカテゴリに分類できます:

  1. データシリアライゼーション形式(XML / JSON / YAML / TOML / CSV / Protobuf など)—— 純粋データ記述型外部 DSL、構造化データを保存・転送可能な形式に変換する
  2. 組み込みスクリプト言語(Lua など)—— 設定と汎用言語の中間に位置し、ホストプログラムにプログラマブルな拡張機能を提供する
  3. インフラストラクチャ定義言語(HCL / Dockerfile など)—— 宣言型外部 DSL、システムの望ましい状態を記述する;Pulumi は内部 DSL の方式で同じ目標を実現する
  4. インターフェース記述言語とグルーコード生成(OpenAPI / .proto)—— 仕様記述を通じてシステム間の接続コードを自動生成する

DSL という分類フレームワークを理解すれば、バックエンドプロジェクトで遭遇するさまざまな「コードらしくないコード」に対して、その性質を素早く識別できるようになります:それがどの種類の DSL に属するか、どの領域の問題を解決するか、なぜ汎用プログラミング言語で書かないのか。

同時に、DSL コードは高度にパターン化され、仕様駆動で、自動検証可能という特徴を持つため、現在の AI コード生成技術が最も効果的に適用できる領域でもあります。