0Pricing
Kotlin Academy · レッスン

型安全なHTML/Config DSLの構築

ビルダーパターンと拡張ラムダを使って、シンプルな設定DSLを実装します。

「型安全なHTML/Config DSLの構築」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。

目標: 実践的な DSL

Kotlin で、最小限ながら現実的な HTML ビルダー DSL を構築します。同じパターンは、設定、テストフィクスチャー、レポートビルダーにも適用できます。完成するのは、文字列連結に代わる、型安全で IDE に適した API です。

Tag 基底クラスを定義する

すべての HTML 要素には、名前、属性、子要素という共通の構造があります。まず基底クラスから始めます。

open class Tag(val name: String) {
    val attrs = mutableMapOf<String, String>()
    val children = mutableListOf<Tag>()
    fun render(indent: Int = 0): String {
        val pad = " ".repeat(indent)
        val attrStr = if (attrs.isEmpty()) "" else " " + attrs.entries.joinToString(" ") { "${it.key}=\"${it.value}\"" }
        val body = children.joinToString("\n") { it.render(indent + 2) }
        return "$pad<$name$attrStr>\n$body\n$pad</$name>"
    }
}

@DslMarker を適用する

すべてのビルダークラスにマークを付け、内側のスコープから外側のスコープのメソッドを誤って呼び出せないようにします。

@DslMarker
annotation class HtmlDsl

@HtmlDsl class Html : Tag("html")
@HtmlDsl class Head : Tag("head")
@HtmlDsl class Body : Tag("body")
@HtmlDsl class Div  : Tag("div")
@HtmlDsl class P   : Tag("p")

ビルダー関数を追加する

各タグクラスに拡張関数を追加します。この関数は子タグを作成し、ブロックを適用して、そのタグを children に追加します。

fun Html.head(block: Head.() -> Unit) = Head().also { it.block(); children += it }
fun Html.body(block: Body.() -> Unit) = Body().also { it.block(); children += it }
fun Body.div(block: Div.() -> Unit) = Div().also { it.block(); children += it }
fun Div.p(text: String) = P().also { it.attrs["text"] = text; children += it }

トップレベルの html ビルダー

ルート要素を作成してユーザーのブロックを適用する、トップレベルのエントリーポイントを用意します。

fun html(block: Html.() -> Unit): Html {
    val root = Html()
    root.block()
    return root
}

DSL を使用する

完成した DSL は、すっきりして読みやすいものになります。

val page = html {
    head { }
    body {
        div {
            p("Hello, DSL!")
        }
    }
}
println(page.render())

属性を追加する

任意の属性を流れるように設定できる attr ヘルパーを追加します。

fun Tag.attr(key: String, value: String) { attrs[key] = value }

// Usage
div {
    attr("class", "container")
    p("Content")
}

設定 DSL パターン

同じパターンは設定オブジェクトにも使えます。HTML タグの代わりに、ドメインクラスを使用します。

class ServerConfig {
    var host = "localhost"
    var port = 8080
    var db: DbConfig? = null
    fun database(block: DbConfig.() -> Unit) { db = DbConfig().apply(block) }
}
fun server(block: ServerConfig.() -> Unit) = ServerConfig().apply(block)

入れ子と合成

各ビルダー関数は作成したオブジェクトを返すため、ビルダーを自由に合成できます。DSL の入れ子の深さは、データ階層の深さと一致します。

型によるエラー防止

型システムによって構造が強制されます。Head には body 拡張関数がないため、Head 内で body { } を呼び出すことはできません。無効な構造はコンパイル時エラーになります。

レンダリングとテスト

DSL は通常の Kotlin オブジェクトツリーを生成するため、レンダリングとテストは簡単です。render() を呼び出して出力文字列を検証するか、テストでオブジェクトツリーを走査できます。

後からDSLを拡張する

新しいタグや設定オプションを追加するには、適切なレシーバークラスに新しい拡張関数を追加するだけです。既存の呼び出し側には影響しません。実際にオープン/クローズドの原則を満たしています。

クイックチェック

KotlinのHTML/config DSLを「型安全」にするものは何ですか?

まとめ:型安全なDSLの構築

主な手順:

  • 階層の各レベルに対応するビルダークラスを定義する
  • レシーバーの漏洩を防ぐために@DslMarkerでアノテーションを付ける
  • 子オブジェクトを生成、設定、追加する拡張関数を記述する
  • トップレベルのエントリーポイント関数を公開する
  • レンダリングとテストは通常のKotlinオブジェクトに対して行う

よくある質問

「型安全なHTML/Config DSLの構築」レッスンは無料ですか?

はい。「型安全なHTML/Config DSLの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。

「型安全なHTML/Config DSLの構築」で何を学びますか?

ビルダーパターンと拡張ラムダを使って、シンプルな設定DSLを実装します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Kotlin Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「型安全なHTML/Config DSLの構築」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このKotlin Academyレッスンでコードを書いて実行できますか?

はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. レシーバー付きLambda:DSLの基盤
  2. @DslMarker:レシーバーの漏洩を防ぐ
  3. 型安全なHTML/Config DSLの構築
  4. ユーザーを壊さずにDSLをテスト・進化させる
← Kotlin Academyに戻る