Macros no Flutter/Dart: A Revolução da Metaprogramação que Você Esperava
Tags: dart, metaprogramming, macros
Published: 2024-06-24 15:12:33


### Macros no Flutter/Dart: A Revolução da Metaprogramação que Você Esperava

![](https://cdn-images-1.medium.com/max/800/0*Z8p1c-66_HrKcMmu.png)

Fala Devs,

No ultimo Google I/O tivemos muitas novidades, e uma delas que era uma das mais esperadas foi a confirmação dos Macros para fase experimental (que significa que logo sairá pra stable).

Mas o que são Macros?

Macros são um recurso que visa revolucionar a metaprogramação, ou seja, a habilidade de escrever código que manipula outros códigos.

Mas o que isso significa?

Imagine uma tarefa comum que realizamos com frequência hoje toJson() e fromJson().

Hoje temos duas maneiras de realizar essa tarefa, podemos simplesmente fazer os métodos na mão.
{% gist https://gist.github.com/toshiossada/2e61d4951d17fe5f89ccec6d81e1eaa4 file=ordinary_log_data.dart %}


![](https://cdn-images-1.medium.com/max/800/1*t43jh436pK_NpzD6DSkztA.png)

O problema desse método é que toda hora que precisamos adicionar um campo novo é no mínimo em 3 lugares que precisamos fazer alteração, um processo que pode ser chato.

![](https://cdn-images-1.medium.com/max/800/1*5T_06om5foDadTjs1kJ0EQ.png)

Outra forma é utilizarmos uma biblioteca terceira que irá gerar todo esse código com a ajuda do odiado build_runner, como por exemplo o json_serializable

![](https://cdn-images-1.medium.com/max/800/1*Ao_xWDzg4YVbJf1ETtfPog.png)

Nesse caso temos alguns fatos que podem frustrar os desenvolvedores, primeiro é que preciso adicionar um “quase” extenso boilerplate

![](https://cdn-images-1.medium.com/max/800/1*XgxHWz9sVjeXoEk9Ixoa1Q.png)

E “outro” problema é que toda alteração precisamos executar novamente o build_runner, as vezes não é um processo tão demorado, entretanto se torna um processo chato de ter que executar o build_runner em toda alteração

![](https://cdn-images-1.medium.com/max/800/1*TJqIrAV_1NUV_9RnXie_lg.png)

![](https://cdn-images-1.medium.com/max/800/1*mTUiwDHXWzOCBXhnhgAiWg.png)

Hoje temos que fazer estes processos pois no dart que está embedado no Flutter é nerfado e não temos a possibilidade de utilizar **Reflections** ou as famigeradas **Mirrors** alegando que há trade-off que talvez não valeria a pena para habilitar as Mirros no Flutter.

![](https://cdn-images-1.medium.com/max/800/1*zqL3yXH2esaOh6S_gELs3A.png)

Mas calma, a equipe do Flutter não deu as costas e ignorou este problema. No Flutter Foward que ocorreu ano passado (2023) eles anunciaram que iriam começar a trabalhar em uma nova feature para resolver este problema, eles anunciaram que brevemente iriam lançar as Macros.

![](https://cdn-images-1.medium.com/max/800/1*jb3jFDIKR4SHTW47bGkP5A.png)

Depois de muita espera, chegaram até rolar boatos que eles iriam desistir das macros, neste Google I/O (2024) eles anunciaram que já encontra em fase experimental.

![](https://cdn-images-1.medium.com/max/800/1*xK7WZXyQMWOcS2fdM7AOKw.png)

Para começar a testar as macros precisamos ter em mente que ainda está em fase experimental, então não está disponível no canal **stable** (Espero que você esteja usando esse canal para desenvolver sus apps) então nossa primeira tarefa para habilitar a utilização dos macros é apontar para o canal master

Execute:

> flutter channel master

![](https://cdn-images-1.medium.com/max/800/1*3ZDQ7KS2K48_kHlo-0KpKw.png)

Isso fará com que apontemos para o dart 3.5

![](https://cdn-images-1.medium.com/max/800/1*lZLYb2xW8wWVqCY-xfJIkw.png)

E se executarmos o comando flutter channel irá nos apresentar que está apontando para a master com um asterisco (*)

![](https://cdn-images-1.medium.com/max/800/1*8oBEq363Yxu1_05Qzq_qCw.png)

Outra etapa (caso use visual studio code) é apontarmos as extensões do dart e flutter para a pré release, procure as extensões e pressione o botão “switch to Pre-Release Version”

![](https://cdn-images-1.medium.com/max/800/1*GWBEnvJA21E78wmwToCkGQ.png)

Faça o mesmo procedimento para o Flutter

![](https://cdn-images-1.medium.com/max/800/1*OoNVnTYYqhwTGKFpAUcv9w.png)

Precisamos também habilitar no analysis_options.yaml a feature experimental dos macros
{% gist https://gist.github.com/toshiossada/3044f07f28ac9d6b3ffcacb6c92490a3 file=analysis_options.yaml %}


![](https://cdn-images-1.medium.com/max/800/1*5wQ-k6W-ccKKENbgS_qu4Q.png)

Pronto agora já podemos utilizar a macros, algo bom que é que não partiremos de um mundo que teremos que criar todas as macros pois a equipe do Dart em paralelo já está desenvolvendo alguns macros que para utiliza-los basta importar em nosso projeto e para esse processo que citamos acima do toJson() e fromJson() existe o pacote json que está publicado por **labs.dart.dev** (publicador da equipe do dart para pacotes que estão em experimental)

![](https://cdn-images-1.medium.com/max/800/1*52wcTBOBZAjJZw04kps6MA.png)

Para adicionar basta executar um **pub add**

![](https://cdn-images-1.medium.com/max/800/1*tHbfaHQG_rkLsKGFaHjnGQ.png)

Para utiliza-lo basta colocarmos a annotation em nossa classe **@JsonCodable()**

![](https://cdn-images-1.medium.com/max/800/1*YV07vKuqea4AlxyzwzBKlg.png)

Note que no VS Code ele habilitou um botão “Go to Augmentation” se clicarmos nele podemos ver os macros que foram gerados

![](https://cdn-images-1.medium.com/max/800/1*phynKe67kWWUo2kOUlnvkw.png)

![](https://cdn-images-1.medium.com/max/800/1*3tTFqJ_5QOfA-wt2RD6FQA.png)

E se alterar o código da classe e salvar ele automaticamente vai alterar minhas macros

![](https://cdn-images-1.medium.com/max/800/1*V9-mSAC3iaTSohKnzNWbVw.gif)

Impressionante a velocidade

![](https://cdn-images-1.medium.com/max/800/1*s92vrLCnhjgKnc93Zln1pg.png)

Outro ponto legal é que também podemos fazer nossos próprios macros, vamos então automatizar a geração do toString()

![](https://cdn-images-1.medium.com/max/800/1*_uN3V0an0X1uHQXiyWeUtw.png)

Notamos que iremos necessitar de 2 informações da classe, o nome da classe e os campos

![](https://cdn-images-1.medium.com/max/800/1*S7Z28bAh9yREHcu6026IPA.png)

Para criar uma classe iremos criar uma class com o modificador macro e devemos implementar a ClassDeclaration, um ponto importante é que fica obrigatório a criação de um construtor que seja constante.

![](https://cdn-images-1.medium.com/max/800/1*vMcYxSJGZueJNHznxuI2Hg.png)

Feito isso implementamos o método **buildDeclarationsForClass** que tem dois parâmetros, a **clazz** (está com Z pois class é uma palavra reservada do dart) que é onde irá conter as informações da classe (como o nome da classe) e também temos o **builder** que iremos utilizar para gerar o código na macro.

Para recuperar o nome da classe utilizamos o clazz.identifier.name e para recuperar os atributos da classe utilizamos o **builder.fieldsOf(clazz)** lembrando que ele é uma Feature então precisamos usar o **await** na execução do método e adicionar o **async** na função.

![](https://cdn-images-1.medium.com/max/800/1*pNJ04KgmZsdX9xnDbCr3Qg.png)

Para gerar o código utilizaremos o builder.declareIntype() e geraremos o código em uma String que podemos separar por virgula(,) para que não fique uma linha gigantesca

![](https://cdn-images-1.medium.com/max/800/1*H8OhrapniMu31ewLC7r-Dw.png)

Ressaltando que a saída do nosso código será “campo: $campo” então é necessário adicionar o **&** com a tag escape na frente (**\**).
{% gist https://gist.github.com/toshiossada/f46d2aa3e9f4fe88ab1ea30909e87783 file=data_clazz.dart %}


Para utiliza-lo em nossa classe basta adicionar a annotation que será o mesmo nome do macro criado.

![](https://cdn-images-1.medium.com/max/800/1*LNErKzXTgi_34spZNVcwQw.png)

E ele automaticamente irá gerar o código no macro

![](https://cdn-images-1.medium.com/max/800/1*lPgSoawVKoxC9g6otmWHxA.png)

Agora podemos utiliza-lo em nosso main.dart
{% gist https://gist.github.com/toshiossada/ed68512917c1350a57f8043ddc48e0c9 file=main.dart %}

Para executar precisamos adicionar a tag — enable-experiment=macros

![](https://cdn-images-1.medium.com/max/800/1*8UhsRujVbdLdf9Xer9qXiw.png)

Ou podemos também deixar configurado em nosso launch.json

![](https://cdn-images-1.medium.com/max/800/1*a5a1tj6HHSL2UD0SBtgMSw.png)

Ressaltando novamente que os macros está em fase experimental e podemos ter alguns bugs que estão sendo corrigidos pela equipe do Dart, mas esperamos que logo(talvez ainda esse ano) já sairá uma versão em em stable para nós deliciar com os macros.

Se quiser ler mais a respeito das macros visite [https://dart.dev/go/macros](https://dart.dev/go/macros)

Tembém gravei um video no canal da Flutter Brasil de como podemos utilizar os macros, confira:

<a href="https://www.youtube.com/watch?v=AjA4sJR2CN8" target="_blank">
 <img src="https://img.youtube.com/vi/AjA4sJR2CN8/0.jpg" alt="Monorepo (Por Que Essa Estratégia Funciona em Grandes Empresas?) " width="240" height="180" border="10" />
</a>

![](https://cdn-images-1.medium.com/max/800/1*12QvPBZZuDYn_fk5raBGNA.png)

Entre em nosso discord para interagir com a comunidade e ficar por dentro de todas as nossas publicações: [https://www.flutterbrasil.com.br](https://www.flutterbrasil.com.br)