Programa
Na engenharia analítica, o dbt (ferramenta de construção de dados) fornecem uma maneira poderosa de escrever lógica SQL dinâmica e reutilizável por meio de blocos de código reutilizáveis.
Neste tutorial, vamos explorar os fundamentos das macros dbt, como criá-las usando Jinja, as melhores práticas para manutenção e aplicações no mundo real, tudo com exemplos de código.
O que são macros dbt?
As macros dbt são blocos de código reutilizáveis escritos usando a linguagem de modelagem Jinja dentro do dbt, que permite gerar SQL de forma dinâmica. Elas ajudam a reduzir a repetição e centralizar a lógica de transformação.
Essas macros funcionam da mesma forma que as funções nas linguagens de programação tradicionais.
Por exemplo, se você precisar calcular uma métrica específica em vários modelos, uma macro pode encapsular esse cálculo, facilitando a manutenção e a atualização.
As macros também podem ser guardadas em pacotes, como o dbt-utils.
Por que usar macros dbt?
As macros têm várias vantagens, principalmente:
- Reduzir a redundância: Você pode escrever um bloco lógico uma vez e reutilizá-lo em qualquer lugar.
- Consistência: Aplicando a mesma lógica de transformação em todos os modelos sem precisar duplicar manualmente.
- Flexibilidade: As macros aceitam parâmetros, o que as torna adaptáveis a várias entradas.
- Compartilhamento entre projetos: Macros bem projetadas podem ser compartilhadas como pacotes.
Esses benefícios resultam em bases de código mais limpas, fáceis de manter e escaláveis.
Conceitos fundamentais da macro dbt
Para ajudar você a entender como as macros funcionam no dbt, vamos dar uma olhada em alguns conceitos importantes.
1. Reutilização
As macros permitem que você defina uma lógica SQL uma vez e a reutilize em vários modelos, testes ou até mesmo em outras macros.
2. Motor de modelagem Jinja
A integração do Jinja com o dbt permite inserir variáveis, aplicar condições e fazer loops em listas, tudo isso antes que seu SQL chegue ao banco de dados. O dbt transforma esse modelo em SQL bruto, tornando as macros independentes do banco de dados.
3. Introdução às técnicas de programação
As macros podem transformar o SQL em uma estrutura programável. Elas permitem lógica, loops e condições — coisas comuns que o SQL padrão não consegue lidar com tanta flexibilidade.
Assim como as funções, as macros no dbt podem aceitar argumentos (parâmetros) e podem ser chamadas com diferentes entradas para produzir diferentes saídas. Elas ajudam a simplificar transformações complexas, dividindo-as em unidades menores e reutilizáveis.
Criando macros com Jinja
Agora, vamos ver como podemos criar algumas macros para nós mesmos.
Jinja é o mecanismo de modelagem que alimenta as macros dbt, permitindo que você trate o SQL como texto dinâmico e programável.
Construções e delimitadores de modelos
Pra usar o Jinja, você vai precisar usar construções de modelo e delimitadores específicos.
Aqui estão algumas construções e delimitadores comuns:
- Expressões
{{ }}: Inserir expressões. - Declarações
{% %}: Executa instruções. - Comentários
{# #}: Adiciona comentários que você quer que o dbt ignore.
Em macros, {{ ... }} é usado para expressões que devem produzir um valor (por exemplo, nomes de colunas ou cálculos), enquanto {% ... %} é usado para fluxo de controle (loops, instruções if/else, definições de macro). Os comentários Jinja usam {# ... #} e são removidos completamente durante a compilação.
Aqui está um exemplo da sintaxe usada para instruções em macros:
{% macro your_macro_name(your_variable) %}
select 'Hello, {{ your_variable}}' as greeting
{% endmacro %}
Aqui vai um exemplo de como usar instruções para criar uma macro:
{% macro greet(name) %}
select 'Hello, {{ name }}' as greeting
{% endmacro %}
Para executar a macro, use isto:
dbt run-operation greet(name) --args 'Austin'
Gerenciamento de variáveis
Você pode passar variáveis para macros ou defini-las dentro delas. Filtros como upper ou lower podem transformar valores de texto.
Aqui está uma implementação da função upper para transformar todos os valores de texto em maiúsculas.
{% macro to_upper_case(column_name) %}
upper({{ column_name }})
{% endmacro %}
Para implementar isso, você teria que chamar/referenciar a macro recém-criada no seu modelo dbt.
Aqui está um exemplo de código:
SELECT
id,
{{ to_upper_case('product_name') }} AS product_name_upper
FROM {{ source('public', 'orders') }}
Estruturas de controle
Em seguida, assim como as linguagens de programação, as macros dbt podem oferecer o seguinte:
- Expressões condicionais (
{% if %}/{% endif %}): - Loops (
{% for %}/{% endfor %})
Essas estruturas permitem que você crie cláusulas SQL de forma dinâmica ou gere várias expressões com base nas entradas.
Isso facilita para as macros lidarem com tarefas complexas de geração de SQL.
Tratamento de parâmetros e gerenciamento de erros
As macros podem validar entradas e gerar erros na hora da compilação para evitar problemas na hora da execução.
Os parâmetros são definidos dentro da declaração da macro usando parênteses (), parecido com as definições de funções nas linguagens de programação.
Aqui está um exemplo de como podemos incluir dois parâmetros:
{% macro my_macro(param1, param2) %}
SELECT
{{ param1 }},
{{ param2 }}
FROM my_table
{% endmacro %}
Como você pode ver, na primeira linha, colocamos tanto param1 quanto param2.
Para chamar a macro em um modelo dbt, você deve usar chaves duplas {{ }}. Os parâmetros são passados como argumentos dentro dos parênteses.
SELECT
id,
{{ my_macro('column_a', 'column_b') }}
FROM my_source_table
Nesse caso, a gente especificou column_a e column_b como nossos parâmetros.
Guia de configuração para trabalhar com macros dbt
Antes de começarmos a criar e usar macros, vamos configurar um ambiente de trabalho para que você possa acompanhar os exemplos deste tutorial.
Isso vai garantir que você tenha o dbt instalado, um conjunto de dados de amostra carregado e a estrutura de pastas certa para criar macros.
1. Instalar o dbt Core
Você vai precisar do dbt Core instalado no seu computador. Se você estiver usando o Postgres neste tutorial, instale com este comando:
pip install dbt
Se o seu projeto usa um warehouse, execute os comandos correspondentes:
pip install dbt-core dbt-postgres
pip install dbt-core dbt-snowflake
pip install dbt-core dbt-bigquery
2. Crie um projeto dbt
Antes de rodarmos qualquer comando dbt, precisamos configurar um ambiente de projeto.
Vá até a pasta dos projetos que você quer.
É aqui que você vai guardar seus arquivos do projeto dbt. Nesse caso, vamos guardar todos os arquivos relacionados nessa pasta do projeto dbt.
Pra começar um projeto dbt, você precisa rodar:
dbt init
cd ~/dbt-macros-tutorial
Crie uma estrutura de pastas com este formato:
macros_tutorial/
├─ models/
├─ macros/
├─ tests/
├─ seeds/
├─ dbt_project.yml
3. Prepare o conjunto de dados de amostra
Vamos usar Python pra gerar um pequeno conjunto de dados de pedidos pra carregar no Postgres (ou no warehouse que você escolher).
import pandas as pd
import random
from datetime import datetime, timedelta
from sqlalchemy import create_engine
# Create sample orders dataframe
random.seed(42)
num_rows = 20
start_date = datetime(2025, 1, 1)
data = []
for i in range(1, num_rows + 1):
order_date = start_date + timedelta(days=random.randint(0, 30))
ship_date = order_date + timedelta(days=random.randint(1, 10))
data.append({
'order_id': i,
'customer_id': random.randint(100, 105),
'order_date': order_date.date(),
'ship_date': ship_date.date(),
'status': random.choice(['pending', 'shipped', 'delivered']),
'revenue': round(random.uniform(50, 500), 2),
'cost': round(random.uniform(20, 400), 2)
})
df = pd.DataFrame(data)
# Load into Postgres
engine = create_engine('postgresql://user:password@localhost:5432/dbt_demo')
df.to_sql('orders', engine, if_exists='replace', index=False)
Observação: Atualize a string de conexão do seu banco de dados.
4. Crie uma fonte no dbt
Adicione o seguinte a models/src_orders.yml:
version: 2
sources:
- name: public
schema: public
tables:
- name: orders
5. Teste a conexão e a fonte
dbt debug
dbt run-operation list_relations --args '{"schema_name": "public"}'
Agora você está pronto para começar a escrever macros que operam neste conjunto de dados.
Como escrever e usar macros dbt
Agora, vamos tentar escrever algumas macros nossas.
Definindo macros
Coloque as definições de macro nos arquivos .sql dentro do diretório macros/.
Ao nomear macros, certifique-se de dar a cada macro um nome descritivo que reflita sua finalidade e use parâmetros para torná-la flexível. Colocar um breve comentário docstring no topo ajuda os colegas de equipe a entender o que se quer dizer.
Aqui vai um exemplo:
-- macros/my_macro.sql
{% macro cents_to_dollars(column_name, precision=2) %}
({{ column_name }} / 100.0)::numeric(18, {{ precision }})
{% endmacro %}
Chamando macros em modelos
Você chama macros dentro de modelos com {{ nome_da_macro(arg1, arg2) }}. Eles podem ser usados em cláusulas SELECT, filtros WHERE ou até mesmo blocos CTE inteiros, permitindo que você insira padrões SQL reutilizáveis em qualquer lugar.
Aqui vai um exemplo:
-- models/my_model.sql
SELECT
order_id,
{{ cents_to_dollars('amount_in_cents') }} AS amount_in_dollars,
{{ cents_to_dollars('tax_in_cents', precision=4) }} AS tax_in_dollars
FROM {{ ref('raw_orders') }}
Chamando macros a partir da CLI
Para tarefas operacionais fora das construções de modelos, use este formato/sintaxe:
dbt run-operation macro_name --args '{"param": "value"}'
Isso permite que você execute SQL utilitário, como criação de esquema ou limpeza de dados, sem construir um modelo.
Aqui está um exemplo de comando:
dbt run-operation greet --args '{"name": "Austin"}'
Usando macros de pacotes
As macros também podem vir de pacotes no dbt, como o dbt-utils.
Quando você instala um pacote pelo packages.yml, as macros dele ficam disponíveis na hora. Pra fazer isso, você vai precisar executar dbt deps.
Você pode então chamar as macros recém-adicionadas com este formato: package_name.macro_name.
Organização de arquivos macro
Para uma melhor organização, classifique e separe as macros por funcionalidade para melhorar a manutenção.
Tente juntar macros parecidas em arquivos separados (por exemplo, date_utils.sql, string_utils.sql) para facilitar a manutenção. Isso facilita localizar e atualizar a lógica ao longo do tempo.
Exemplos de macros dbt na prática
Aqui estão alguns exemplos de macros em casos de uso mais práticos:
Macro de comparação de datas
Digamos que você queira criar uma função que vai usar bastante para comparar datas.
Nesse caso, você pode usar uma macro para calcular as diferenças de dias entre dois campos de data enquanto lida com as diferenças de dialeto SQL.
Comece criando um novo arquivo aqui: macros/date_utils.sql.
Depois, usa o seguinte código:
{% macro days_between(start_col, end_col) %}
{#-- Handle different warehouses --#}
{% if target.type in ['postgres', 'redshift'] %}
(DATE_PART('day', {{ end_col }}::timestamp - {{ start_col }}::timestamp))
{% elif target.type in ['snowflake'] %}
DATEDIFF('day', {{ start_col }}, {{ end_col }})
{% elif target.type in ['bigquery'] %}
DATE_DIFF(CAST({{ end_col }} AS DATE), CAST({{ start_col }} AS DATE), DAY)
{% else %}
-- Fallback to ANSI-ish expression; may need adjustment per engine
CAST({{ end_col }} AS DATE) - CAST({{ start_col }} AS DATE)
{% endif %}
{% endmacro %}
Agora, vamos usar essa nova macro days_between em um modelo.
with src as (
select * from {{ source('public', 'orders') }}
)
select
order_id,
customer_id,
order_date,
ship_date,
{{ days_between('order_date', 'ship_date') }} as days_to_ship
from src
Personalizado generate_schema_name macro
Por padrão, o dbt usa uma macro chamada ` generate_schema_name`. Essa macro é usada para especificar o nome do esquema no qual um modelo deve ser construído.
Você também pode substituir a configuração padrão do dbt para controlar o esquema usado por ambiente.
Você pode incluir esse arquivo no seguinte local: macros/generate_schema_name.sql.
`sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{# Policy:
- prod: ANALYTICS
- nonprod: dev_analytics, ci_analytics, etc.
#}
{%- if target.name == 'prod' -%}
{{ custom_schema_name | trim }}
{%- else -%}
{{ (target.name ~ '_' ~ custom_schema_name) | lower | replace(' ', '_') }}
{%- endif -%}
{%- endmacro %}
Como isso ajuda: No dev, os modelos chegam ao ambiente de isolamento ( dev_analytics ). Em prod, eles chegam a analytics. Isso cria implementações previsíveis e sem conflitos.
Executando SQL fora de um modelo
Você também pode executar comandos SQL fora dos modelos para operações como limpeza de tabelas ou atualizações de metadados sem criar modelos.
Você pode criar uma macro que execute SQL bruto e depois rodá-la usando dbt run-operation.
Isso é útil para DDL (exclusão/criação de tabelas) ou atualizações de metadados que não se encaixam em um modelo.
Aqui está a macro:
{% macro cleanup_temp_tables() %}
{% set sql %}
drop table if exists {{ target.schema }}.temp_table;
delete from {{ target.schema }}.audit_log where event_type = 'test';
{% endset %}
{{ run_query(sql) }}
{% endmacro %}
Depois, execute esta operação no terminal:
dbt run-operation cleanup_temp_tables
Isso vai te deixar rodar macros sem precisar colocá-las nos modelos.
Exemplo de macro parametrizada
Também dá pra criar uma macro super parametrizada, tipo numa função.
Neste exemplo, vamos filtrar registros com base em um determinado status, que é quando os valores são fornecidos. Isso usa as instruções ` if ` e ` do ` para criar lógica.
{% macro where_orders(status=None, min_date=None, max_date=None) %}
{%- set clauses = [] -%}
{%- if status is not none -%}
{%- do clauses.append("status = '" ~ status ~ "'") -%}
{%- endif -%}
{%- if min_date is not none -%}
{%- do clauses.append("order_date >= '" ~ min_date ~ "'") -%}
{%- endif -%}
{%- if max_date is not none -%}
{%- do clauses.append("order_date < '" ~ max_date ~ "'") -%}
{%- endif -%}
{%- if clauses | length > 0 -%}
where {{ clauses | join(' and ') }}
{%- endif -%}
{% endmacro %}
Agora vamos aplicar essa macro em um modelo:
with src as (
select * from {{ ref('orders') }}
)
select *
from src
{{ where_orders(status='shipped', min_date='2025-01-05') }}
Essa macro tem uma lógica para quando um argumento é esquecido; esse critério é ignorado. Isso mantém a lógica opcional organizada.
Melhores práticas para macros dbt
Criar macros excelentes é mais do que apenas compilar o SQL. As melhores macros são fáceis de encontrar, bem documentadas, previsíveis, testáveis e fáceis de descontinuar ou estender.
Aqui estão algumas dicas para você seguir:
1. Convenções de nomenclatura e design de parâmetros
Assim como no SQL e nas linguagens de programação, é preciso seguir as convenções de nomenclatura para garantir a legibilidade.
Aqui vão algumas dicas para nomear:
- Seja direto e focado em ações. Prefira verbos ou intenções claras (por exemplo,
generate_select_list,where_orders) em vez de nomes vagos comohelper. - Mantenha os nomes estáveis e em minúsculas. Use snake_case e prefixos estáveis por domínio, por exemplo,
date_*,string_*,test_*,admin_*.
2. Estratégias de documentação
Você deve criar hábitos que ajudem a documentar o que você faz. A documentação deve ser feita em lugares onde os desenvolvedores procuram.
Por exemplo, combine strings de documentação inline + um macros.yml (ou schema.yml) com descrições e exemplos.
O conteúdo da documentação pode incluir:
- Objetivo e resultado esperado (1–2 frases)
- Tabela de parâmetros com valores padrão e permitidos
- Exemplo curto de invocação em um modelo e com
run-operation - Notas sobre o comportamento entre bancos de dados
Exemplo de trecho de um arquivo de configuração:
version: 2
macros:
- name: days_between
description: |
Return day difference between two date expressions, normalized across warehouses.
arguments:
- name: start_col
type: string
description: Column/expression for the start date
- name: end_col
type: string
description: Column/expression for the end date
docs:
show: true
3. Organização do código
Seu código também precisa estar bem organizado, principalmente quando você tem que lidar com um monte de macros no seu diretório.
Tente organizar por domínio pra facilitar o uso. Aqui estão alguns exemplos disso:
macros/date_utils.sqlmacros/string_utils.sqlmacros/testing/(testes personalizados)macros/admin/(DDL, tarefas domésticas)macros/compat/(calços de warehouse)
4. Mantenha as macros pequenas e com uma única finalidade
Uma macro deve fazer bem uma coisa. Se você perceber que uma macro está ficando muito grande ou lidando com lógica não relacionada, divida-a em macros menores. Isso melhora a reutilização e torna os testes mais simples.
5. Teste as macros com dados representativos
Use modelos de teste específicos ou um ambiente de teste para ver se o comportamento da macro tá certo.
Por exemplo:
- Crie um pequeno conjunto de dados inicial que cubra casos extremos.
- Escreva um modelo de teste que chame a macro com diferentes parâmetros.
- Use
dbt rune veja se o SQL compilado está certo.
Dica profissional: Combine macros com testes personalizados d dbt test e para verificar se os resultados atendem às restrições esperadas.
Casos de uso e aplicações comuns
As macros dbt são versáteis e suas aplicações se estendem a muitos fluxos de trabalho diários de engenharia analítica.
Aqui estão alguns exemplos mais detalhados:
- Padronizando as transformações de dados: As macros podem garantir que as mesmas convenções de nomenclatura, corte, tratamento de nulos e lógica de conversão de tipos sejam aplicadas a vários modelos. Por exemplo, você pode criar uma macro
standardize_customer_namepara limpar e formatar nomes de forma idêntica em todos os marts. - Suporte a consultas entre bancos de dados: Os warehouses têm diferenças sutis no dialeto SQL. As macros podem abstrair essas diferenças, como usar
DATEDIFFno Snowflake eDATE_DIFFno BigQuery. Isso deixa seus modelos portáteis. - Automatizando as verificações de qualidade: Escreva macros reutilizáveis que geram testes de dados, como verificar se há IDs duplicados, colunas críticas nulas ou valores fora do intervalo. Eles podem ser usados em vários modelos de teste.
- Simplificando padrões SQL repetitivos: CTEs comuns, campos calculados ou cláusulas de filtragem podem ser parametrizados em macros. Por exemplo, uma macro para criar cláusulas dinâmicas
WHEREcom base em filtros opcionais evita a necessidade de copiar e colar lógicas complexas.
Técnicas avançadas e otimização de desempenho
As macros dbt também podem ser usadas em aplicações mais avançadas. Vamos ver duas maneiras comuns abaixo.
Padrões recursivos e de metaprogramação
As macros podem chamar outras macros, percorrer metadados ou gerar fragmentos SQL de forma dinâmica com base na inspeção do esquema.
Isso permite que você:
- Crie automaticamente modelos de preparação para cada tabela de origem.
- Crie consultas pivot/unpivot sem precisar digitar cada coluna manualmente.
- Crie consultas que levam em conta o ambiente, fazendo um loop pelas variáveis de configuração.
Estratégias de otimização de desempenho
Você também pode fazer mais otimizações pra ajudar a melhorar o desempenho:
- Minimize a complexidade da consulta incluindo seletivamente apenas as colunas ou junções necessárias.
- Ajuste as materializações ou estratégias SQL com base no tipo de warehouse.
Integração com o ecossistema dbt
As macros são feitas pra fazer parte do ecossistema dbt, o que as deixa ainda mais poderosas quando usadas junto com pacotes, recursos na nuvem e ferramentas externas.
Gerenciamento de pacotes
Muitos pacotes dbt comunitários, como dbt-utils, dbt-date e dbt-expectations, são basicamente coleções de macros super reutilizáveis.
Esses pacotes trazem transformações, testes e auxiliares pré-construídos, sem precisar reinventar a roda.
Compatibilidade com o dbt Nuvem e ferramentas de desenvolvimento
As macros funcionam perfeitamente nos ambientes dbt Cloud, o que significa que sua lógica SQL dinâmica se comporta da mesma forma, seja executada localmente ou em uma tarefa agendada na nuvem.
Eles também se integram bem com controle de versão, pipelines de CI/CD e processos de revisão de código, garantindo que as atualizações macro sejam testadas e implantadas de forma consistente.
Estratégias de implementação no mundo real
Passar dos scripts SQL tradicionais para um fluxo de trabalho dbt baseado em macros exige mudanças técnicas e uma adaptação cultural.
Migração e gerenciamento de mudanças
Ao migrar, comece identificando padrões SQL repetidos entre os modelos. Depois, refatore isso em macros aos poucos, conferindo se o SQL compilado bate com a lógica antiga.
Use sinalizadores de recurso (var()) para ativar/desativar a nova lógica macro durante a implementação, minimizando as interrupções. O mais importante é que você vai querer que seus stakeholders fiquem por dentro das mudanças pra evitar que as consultas a jusante sejam interrompidas.
Estratégias de governança e implantação
Para a governança, comece estabelecendo convenções de nomenclatura claras, padrões de parâmetros e requisitos de documentação para todas as macros.
Depois, dá uma olhada nas mudanças macro nas solicitações de pull, assim como nas atualizações do modelo, pra garantir que elas atendam aos padrões de desempenho e compatibilidade.
Na produção, fique de olho nos registros de tarefas para consultas geradas por macro para ver se elas estão funcionando como esperado. Para projetos com muitas macros, crie painéis de observabilidade para acompanhar os tempos de compilação e o desempenho das consultas por tipo de macro.
Conclusão
As macros dbt são uma parte essencial da produtividade e manutenção em equipes modernas de engenharia analítica. Usar modelos dbt junto com macros pode trazer resultados melhores para as operações de limpeza de dados.
Quer saber mais sobre o dbt? Nossa Introdução ao dbt e Tutorial dbt podem ser úteis para você.
Perguntas frequentes sobre macros dbt
Como posso otimizar o desempenho das minhas macros dbt?
O segredo é garantir que o SQL que sua macro gera seja eficiente. Evite usar loops para construir SQL linha por linha. Tente deixar o banco de dados cuidar das coisas com consultas baseadas em conjuntos. Além disso, mantenha as macros focadas e evite adicionar muitas camadas de lógica que geram SQL excessivamente complexo. Se você perceber que está repetindo o mesmo cálculo, pense em armazená-lo em cache dentro da macro ou movê-lo para um modelo.
Quais são algumas das armadilhas comuns ao usar macros dbt?
Um erro comum é complicar demais as macros, a ponto de torná-las difíceis de entender ou depurar. Outro é não pensar nas diferenças entre os bancos de dados. Às vezes, você pode esquecer de escapar variáveis, o que pode causar erros ou gerar SQL ilegível para seus colegas de equipe.
Como faço para resolver problemas com macros dbt?
Comece verificando o SQL compilado na pasta target/compiled. Esse arquivo mostra exatamente o que a macro produziu. Você também pode adicionar instruções {{ log('message', info=True) }} dentro da sua macro para ver o que está acontecendo durante a execução. Se algo der errado, simplifique as entradas e teste com exemplos menores usando o comando dbt run-operation até encontrar o problema.
As macros dbt podem ser usadas com outras ferramentas ou frameworks?
Sim, mas só pelo próprio dbt. Por exemplo, ferramentas como Airflow ou Dagster podem executar comandos dbt que chamam suas macros. No dbt, as macros também podem ser compartilhadas por meio de pacotes como o dbt-utils. Mas, você não pode rodar uma macro dbt diretamente em outra ferramenta, a menos que você a coloque dentro de um comando dbt.
Quais são as melhores práticas para documentar macros dbt?
Algumas das melhores práticas são pensar nas macros como pequenas funções que outras pessoas usarão. Também pense em escrever descrições claras do que eles fazem, listando todos os argumentos (com padrões, se possível) e mostre exemplos curtos de como usá-los. Se a macro agir de forma diferente em bancos de dados diferentes, anote isso também. Uma boa documentação facilita para os colegas de equipe confiarem e reutilizarem seu trabalho.

Sou Austin, blogueiro e escritor de tecnologia com anos de experiência como cientista de dados e analista de dados na área de saúde. Iniciando minha jornada tecnológica com formação em biologia, agora ajudo outras pessoas a fazer a mesma transição por meio do meu blog de tecnologia. Minha paixão por tecnologia me levou a contribuir por escrito para dezenas de empresas de SaaS, inspirando outras pessoas e compartilhando minhas experiências.

