1 de novembro de 2021

Gerando código que gera código

Alguns anos atrás lendo o Programador Pragmático eu esbarrei em um conceito muito interessante, geração de código. O caso de uso era simples: em alguns momentos você precisava produzir diversas estruturas de código, as vezes em mais de uma linguagem, que seguiam os mesmos padrões e para evitar o trabalho manual era interessante fazer um gerador de código.

O caso do livro era a geração de algumas estruturas de dados em diversas linguagens e aproveitando o aprendizado eu decidi estender o conceito para a geração de classes (projeto aqui), para isso era lido um código simples dizendo o nome da classe, seus atributos e também os modificadores de acesso, como abaixo:

B + Pessoa 
A - nome:String
A - teste1:int
A # teste:char[10]
A # teste:teste[56]
A + desprotegido:float
A - teste:float[34543]
E 

Como podemos ver temos a definição de cada linha pela primeira letra, depois o modificador do atributo seguido de seu nome e tipo. É algo muito simples, mas lembro que foi neste exemplo a primeira vez que eu ouvi falar de expressões regulares, afinal o gerador de código era feito em Perl e expressões regulares para Perl são algo intrínseco da linguagem. Um exemplo das classes geradas em Java, C++ e PHP a partir da especificação acima é o abaixo:

O conceito é poderoso, apesar de simples, afinal isso mostrou que a partir de uma especificação eu poderia gerar código, ou se quisermos ir um pouco além, significava que a partir de uma linguagem em poderia gerar código em outras linguagens.

Com este aprendizado fiz alguns outros geradores de código, principalmente geração de comandos a partir de alguma lista de dados. O que mais usei foi um script para geração de comandos de macro para o TeraTerm (programa de terminal) permitindo automatizar diversas tarefas.

Voltando para o conceito inicial do Programador Pragmático, o principal motivo de utilizar um gerador de código era evitar a duplicidade de código, o que é confuso, pois no final do meu exemplo acima o código estava triplicado, o que é verdade, mas nem tanto. Como a geração destas classes estava atrelada a um único arquivo de especificação a regra estava centralizada e o código gerado era praticamente um asset do meu projeto.

Este conceito de geração de código inclusive pode ser uma sementinha inicial para outras coisas mais profundas, como criação de linguagens de script, compiladores e afins. No livro Crafting Intepreters que já citei aqui no blog mais de uma vez, além da geração de código "óbvia" que a construção de um compilador faz, o autor se aproveita do conceito mais simples de script de geração de código para gerar a árvore de sintaxe abstrada, permitindo assim após ter o script de geração ampliar a sintaxe apenas mudando algumas especificações. 

Provavelmente você faz ou já fez uso de alguma ferramenta de geração de código e também poderia se aproveitar do conceito em algum momento para economizar tempo e diminuir a quantidade de erros gerados pelo fardo da repetição.

Nenhum comentário:

Postar um comentário