Introducció

Un DSL (Domain-Specific Language) és un llenguatge de programació o especificació dedicat a un domini particular. Groovy és especialment adequat per crear DSLs gràcies a la seva sintaxi flexible i les seves capacitats de metaprogramació. En aquest tema, explorarem com crear i utilitzar DSLs en Groovy.

Conceptes Clau

  1. DSL Intern vs. DSL Extern:

    • DSL Intern: Un DSL que s'implementa dins d'un llenguatge de programació existent, aprofitant la seva sintaxi i semàntica.
    • DSL Extern: Un DSL que té la seva pròpia sintaxi i es processa per separat del llenguatge de programació principal.
  2. Closures: Les closures són una característica poderosa de Groovy que permeten definir blocs de codi reutilitzables i són fonamentals per a la creació de DSLs.

  3. Builders: Els builders són una tècnica comuna en Groovy per construir DSLs. Utilitzen closures per definir estructures jeràrquiques de manera clara i concisa.

Exemples Pràctics

Exemple 1: Un DSL per Configurar una Persona

Comencem amb un exemple senzill d'un DSL per configurar una persona.

class Person {
    String name
    int age
    String address

    String toString() {
        return "Person(name: $name, age: $age, address: $address)"
    }
}

def person(Closure closure) {
    def p = new Person()
    closure.delegate = p
    closure()
    return p
}

def p = person {
    name = 'John Doe'
    age = 30
    address = '123 Main St'
}

println p

Explicació:

  • Definim una classe Person amb tres propietats: name, age i address.
  • La funció person accepta una closure que configura una instància de Person.
  • La closure s'executa amb delegate establert a l'objecte Person, permetent l'assignació directa de propietats.

Exemple 2: Un DSL per Definir una Estructura XML

Ara, crearem un DSL per construir una estructura XML.

class XmlBuilder {
    def xml = new StringBuilder()

    def methodMissing(String name, args) {
        xml << "<$name>"
        args[0].delegate = this
        args[0]()
        xml << "</$name>"
    }

    String toString() {
        return xml.toString()
    }
}

def xml = new XmlBuilder()
xml.root {
    person {
        name { xml << 'John Doe' }
        age { xml << '30' }
        address { xml << '123 Main St' }
    }
}

println xml

Explicació:

  • XmlBuilder utilitza methodMissing per capturar les crides de mètodes no definits i construir l'estructura XML.
  • Les closures s'utilitzen per definir el contingut dels elements XML.

Exercicis Pràctics

Exercici 1: Crear un DSL per Configurar un Vehicle

Crea un DSL per configurar un vehicle amb les propietats make, model i year.

class Vehicle {
    String make
    String model
    int year

    String toString() {
        return "Vehicle(make: $make, model: $model, year: $year)"
    }
}

def vehicle(Closure closure) {
    def v = new Vehicle()
    closure.delegate = v
    closure()
    return v
}

def v = vehicle {
    make = 'Toyota'
    model = 'Corolla'
    year = 2020
}

println v

Exercici 2: Crear un DSL per Definir un Menú de Restaurant

Crea un DSL per definir un menú de restaurant amb categories i plats.

class MenuBuilder {
    def menu = new StringBuilder()

    def methodMissing(String name, args) {
        menu << "$name:\n"
        args[0].delegate = this
        args[0]()
    }

    def dish(String name, double price) {
        menu << "  - $name: \$${price}\n"
    }

    String toString() {
        return menu.toString()
    }
}

def menu = new MenuBuilder()
menu.menu {
    appetizers {
        dish 'Bruschetta', 5.99
        dish 'Stuffed Mushrooms', 6.99
    }
    main_courses {
        dish 'Grilled Salmon', 15.99
        dish 'Steak', 19.99
    }
    desserts {
        dish 'Cheesecake', 7.99
        dish 'Tiramisu', 6.99
    }
}

println menu

Resum

En aquest tema, hem après què són els DSLs i com Groovy facilita la seva creació gràcies a la seva sintaxi flexible i les closures. Hem vist exemples pràctics de DSLs per configurar objectes i construir estructures XML, i hem practicat amb exercicis per reforçar els conceptes apresos. Amb aquestes eines, pots començar a crear els teus propis DSLs per simplificar i fer més expressiu el teu codi en dominis específics.

© Copyright 2024. Tots els drets reservats