SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
26.11.2024

Lição: 143: DSLs em Swift

As Linguagens Específicas de Domínio (DSLs) são linguagens especializadas criadas para domínios de aplicação específicos. Em Swift, criar DSLs pode aumentar a legibilidade do código e proporcionar uma forma mais intuitiva de expressar lógicas complexas. Nesta aula, vamos explorar como desenvolver uma DSL em Swift, oferecendo exemplos ao longo do caminho.

O que é uma DSL?

Uma DSL foca em resolver problemas dentro de um domínio específico, permitindo uma sintaxe mais expressiva e concisa. Isso é particularmente útil em áreas como configuração, validação de dados e representação de interfaces.

Criando uma DSL Simples

Vamos considerar um exemplo simples: uma DSL para construir um documento HTML básico.

Passo 1: Definindo a Estrutura HTML

Começaremos definindo uma estrutura básica para nossos elementos HTML usando as classes do Swift.

class HTMLElement {
    let nome: String
    var atributos: [String: String] = [:]
    var filhos: [HTMLElement] = []

    init(nome: String) {
        self.nome = nome
    }

    func setAtributo(chave: String, valor: String) {
        atributos[chave] = valor
    }

    func adicionarFilho(_ filho: HTMLElement) {
        filhos.append(filho)
    }

    func renderizar() -> String {
        let atributosString = atributos.map { "\($0.key)=\"\($0.value)\"" }.joined(separator: " ")
        let tagAberta = "<\(nome)\(atributosString.isEmpty ? "" : " " + atributosString)>"
        let tagFechada = "</\(nome)>"
        let filhosString = filhos.map { $0.renderizar() }.joined()

        return "\(tagAberta)\(filhosString)\(tagFechada)"
    }
}

Passo 2: Criando um Construtor para Nossa DSL

Em seguida, desenvolvemos um construtor que nos permite definir elementos HTML em uma sintaxe mais natural.

@resultBuilder
struct HTMLBuilder {
    static func buildBlock(_ componentes: HTMLElement...) -> HTMLElement {
        let pai = HTMLElement(nome: "html")
        componentes.forEach { pai.adicionarFilho($0) }
        return pai
    }

    // Funções adicionais de construção podem ser definidas para lidar com diferentes tipos de declarações
}

func html(@HTMLBuilder conteudo: () -> HTMLElement) -> HTMLElement {
    return conteudo()
}

Passo 3: Usando a DSL

Agora podemos criar documentos HTML usando nossa DSL.

let documento = html {
    let cabeca = HTMLElement(nome: "head")
    cabeca.adicionarFilho(HTMLElement(nome: "title"))

    let corpo = HTMLElement(nome: "body")
    let paragrafo = HTMLElement(nome: "p")
    paragrafo.setAtributo(chave: "class", valor: "texto")

    corpo.adicionarFilho(paragrafo)

    return cabeca
    return corpo
}

// Renderizando o documento
print(documento.renderizar())

Passo 4: Melhorias

Podemos melhorar ainda mais nossa DSL adicionando mais funcionalidades, como tags auto-fechadas ou elementos HTML adicionais.

extension HTMLElement {
    static func br() -> HTMLElement {
        return HTMLElement(nome: "br")
    }

    static func img(src: String, alt: String) -> HTMLElement {
        let elementoImg = HTMLElement(nome: "img")
        elementoImg.setAtributo(chave: "src", valor: src)
        elementoImg.setAtributo(chave: "alt", valor: alt)
        return elementoImg
    }
}

Exemplo com Melhorias

Aqui está um exemplo que utiliza as novas funcionalidades:

let documentoMelhorado = html {
    let cabeca = HTMLElement(nome: "head")
    cabeca.adicionarFilho(HTMLElement(nome: "title"))

    let corpo = HTMLElement(nome: "body")
    corpo.adicionarFilho(HTMLElement.img(src: "imagem.png", alt: "Imagem de Exemplo"))
    corpo.adicionarFilho(HTMLElement.br())

    return cabeca
    return corpo
}

// Renderizando o documento melhorado
print(documentoMelhorado.renderizar())

Conclusão

Criar DSLs em Swift pode melhorar significativamente a legibilidade e a manutenibilidade do seu código. Esta aula demonstrou como construir uma DSL simples para HTML; no entanto, você pode aplicar padrões semelhantes a outros domínios, como arquivos de configuração, layouts de interface ou até mesmo frameworks de teste. Ao aproveitar os poderosos recursos do Swift, como construtores de resultados, você pode criar um código conciso e expressivo que comunica claramente suas intenções.

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!