0Pricing
Kotlin Academy · درس

إنشاء DSL آمن للأنواع لـ HTML/Config

نفّذ DSL بسيطًا للإعدادات باستخدام أنماط البناء وامتدادات lambda.

إنشاء DSL آمن للأنواع لـ HTML/Config درس مجاني في Kotlin Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Kotlin Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

الهدف: إنشاء DSL عملية

سنبني DSL بسيطة لكنها واقعية لإنشاء HTML في Kotlin. وتنطبق الأنماط نفسها على أي منشئ إعدادات أو تركيبات اختبار أو تقارير. والنتيجة هي واجهة برمجة تطبيقات آمنة النوع وملائمة لبيئة التطوير المتكاملة، تستبدل دمج السلاسل النصية.

تعريف الفئة الأساسية للوسم

تشترك جميع عناصر 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")

إضافة دوال البناء

تحصل كل فئة وسم على دالة امتداد تنشئ وسمًا فرعيًا، وتطبّق الكتلة، ثم تضيفه إلى العناصر الفرعية:

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 مع عمق التسلسل الهرمي للبيانات.

منع الأخطاء باستخدام الأنواع

يفرض نظام الأنواع البنية المطلوبة: لا يمكنك استدعاء body { } داخل Head لأن Head لا تملك دالة امتداد body. وتصبح البنى غير الصالحة أخطاءً في وقت الترجمة.

التصيير والاختبار

بما أن DSL تنتج شجرة كائنات عادية في Kotlin، فإن التصيير والاختبار مباشران: استدعِ render() وتحقّق من سلسلة الناتج، أو تجوّل في شجرة الكائنات داخل الاختبارات.

توسعة DSL لاحقًا

لا تتطلب إضافة وسوم أو خيارات إعداد جديدة سوى إضافة دوال توسعة جديدة إلى صنف المستقبل المناسب. ولا تتأثر مواضع الاستدعاء الحالية — وهذا يحقق مبدأ الانفتاح والإغلاق عمليًا.

تحقق سريع

ما الذي يجعل DSL الخاص بـ Kotlin لإنشاء HTML أو الإعدادات «آمنًا من حيث الأنواع»؟

مراجعة: بناء DSL آمن من حيث الأنواع

الخطوات الأساسية:

  • تعريف أصناف بنّاء لكل مستوى من مستويات التدرج الهرمي
  • استخدام @DslMarker لمنع تسرّب المستقبلات
  • كتابة دوال توسعة تنشئ الكائنات التابعة وتضبطها وتضيفها
  • إتاحة دالة نقطة دخول على مستوى الحزمة
  • يعمل العرض والاختبار على كائنات Kotlin عادية

الأسئلة الشائعة

هل درس «إنشاء DSL آمن للأنواع لـ HTML/Config» مجاني؟

نعم — نص درس «إنشاء DSL آمن للأنواع لـ HTML/Config» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Kotlin Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Kotlin Academy 4 دروس في المجموع.

ماذا ستتعلم في «إنشاء DSL آمن للأنواع لـ HTML/Config»؟

نفّذ DSL بسيطًا للإعدادات باستخدام أنماط البناء وامتدادات lambda. تتمرن على Kotlin Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Kotlin Academy؟

لا تُشترط خبرة سابقة. Kotlin Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «إنشاء DSL آمن للأنواع لـ HTML/Config»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Kotlin Academy هذا؟

نعم. كل درس في Kotlin Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. Lambda مع مستقبل: أساس DSL
  2. @DslMarker: منع تسرّب المستقبلات
  3. إنشاء DSL آمن للأنواع لـ HTML/Config
  4. اختبار DSL وتطويره من دون التأثير في المستخدمين
← العودة إلى Kotlin Academy