DEV Community

Cover image for Advanced Kotlin DSL: Building Smart Builders with Validation and Error Aggregation
Den B
Den B

Posted on

1

Advanced Kotlin DSL: Building Smart Builders with Validation and Error Aggregation

Kotlin DSLs are often used for configuration or UI building, but they rarely enforce correctness at compile or runtime. You can enhance DSLs with declarative validation logic, using internal builder patterns to collect multiple errors at once—an uncommon but highly powerful pattern.

✅ Use Case: Validating a DSL for Form Submission Logic

Instead of failing fast on the first error, we want to collect all configuration errors and then fail with full diagnostics.

⚙️ DSL with Validation Support

@DslMarker
annotation class FormDsl

@FormDsl
class FormBuilder {
    private val errors = mutableListOf<String>()
    private var name: String? = null
    private var email: String? = null

    fun name(value: String) {
        if (value.isBlank()) errors += "Name cannot be blank"
        name = value
    }

    fun email(value: String) {
        if (!value.contains("@")) errors += "Invalid email format"
        email = value
    }

    fun build(): Form {
        if (errors.isNotEmpty()) {
            throw IllegalArgumentException("Form validation failed:\n" + errors.joinToString("\n"))
        }
        return Form(name!!, email!!)
    }
}

data class Form(val name: String, val email: String)

fun form(block: FormBuilder.() -> Unit): Form =
    FormBuilder().apply(block).build()
Enter fullscreen mode Exit fullscreen mode

✅ Usage:

val form = form {
    name("")
    email("no-at-symbol")
}
// Throws with detailed error report:
// - Name cannot be blank
// - Invalid email format
Enter fullscreen mode Exit fullscreen mode

📌 Notes for Quick Reference
• ✅ Use errors: MutableList to accumulate configuration mistakes.
• ✅ Use @DslMarker to prevent scope collisions.
• ❌ Avoid throwing inside individual DSL methods—defer until .build().
• ✅ Ideal for CI/CD DSLs, Terraform-style Kotlin config, or complex form builders.

🚀 Pro Tip: Add warning() support next to error() to flag non-blocking suggestions during DSL execution, mimicking compiler diagnostics.

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (0)

Sentry image

Make it make sense

Make sense of fixing your code with straight-forward application monitoring.

Start debugging →

👋 Kindness is contagious

If you found this post useful, consider leaving a ❤️ or a nice comment!

Got it