Blog

  • Engenharia de Prompt + Programação: Como Trabalhar com IA na Prática (Com Código Python Integrado)

    Engenharia de Prompt + Programação: Como Trabalhar com IA na Prática (Com Código Python Integrado)

    A engenharia de prompt não é só sobre escrever frases bonitas para a IA.

    Na prática, os engenheiros de prompt que mais faturam são aqueles que sabem integrar o poder da linguagem natural com a lógica da programação. Eles criam automações, aplicações, sistemas inteligentes e fluxos de trabalho reais que resolvem problemas — e cobram bem por isso.

    Se você quer ver como é o dia a dia de um engenheiro de prompt que também programa, chegou no lugar certo.

    Neste artigo você vai entender:

    ✅ Como usar Python para se comunicar com IA
    ✅ Como estruturar prompts para contextos técnicos
    ✅ Como integrar IA a APIs, bancos de dados e sistemas reais
    ✅ Como gerar código, transformar texto em ação e criar automações inteligentes

    Prepare seu VSCode e vem comigo.

    1. O básico: como usar Python para se comunicar com a OpenAI

    Antes de mais nada, o engenheiro de prompt precisa integrar sua aplicação com o modelo da OpenAI (ex: GPT-4). Com a biblioteca oficial, isso é simples.

    pip install openai
    
    import openai
    
    openai.api_key = 'SUA_CHAVE_AQUI'
    
    def gerar_resposta(prompt):
        resposta = openai.ChatCompletion.create(
            model='gpt-4',
            messages=[
                {'role': 'system', 'content': 'Você é um especialista em código Python.'},
                {'role': 'user', 'content': prompt}
            ]
        )
        return resposta['choices'][0]['message']['content']

    Agora, qualquer prompt técnico pode ser enviado, e a resposta utilizada dentro do seu código.

    2. Gerando código real com prompts

    Imagine que você precisa de um script para ler dados de um arquivo CSV e salvar em um banco SQLite. Em vez de escrever tudo na unha, use um prompt direcionado:

    prompt = """
    Gere um código Python que leia um arquivo CSV chamado 'dados.csv', trate os dados removendo linhas vazias,
    e insira o conteúdo em uma tabela chamada 'usuarios' em um banco SQLite chamado 'meubanco.db'.
    """
    print(gerar_resposta(prompt))

    O retorno será um código funcional, que pode ser executado, testado e adaptado.
    Isso acelera o desenvolvimento e transforma o programador em um arquiteto de soluções.

    3. Criando assistentes de programação personalizados

    Você pode ir além e construir um assistente de programação que aprende com seu projeto. Basta injetar o contexto correto:

    def gerar_assistente(contexto_codigo, tarefa):
        return gerar_resposta(f"""
    Você está ajudando a desenvolver um sistema. Aqui está o código existente:
    {contexto_codigo}
    
    Baseado nisso, {tarefa}
    """)

    Exemplo de uso:

    codigo_existente = open('app.py').read()
    tarefa = "crie uma nova função que calcula o total de vendas por cliente"
    print(gerar_assistente(codigo_existente, tarefa))
    

    A IA entenderá o código e proporá complementos compatíveis.

    4. Criando uma API REST com IA ajudando em cada etapa

    Imagine que você quer gerar uma API Flask. Você pode iterar com a IA passo a passo:

    etapas = [
        "crie um esqueleto básico de uma API REST com Flask",
        "adicione rota POST para cadastrar usuário (nome, email)",
        "adicione rota GET que lista todos os usuários (use SQLite)",
        "adicione autenticação por token na rota POST"
    ]
    
    for etapa in etapas:
        print(gerar_resposta(etapa))

    A cada etapa, a IA te devolve um trecho do código — você insere no projeto, testa e continua.
    Você programa guiado por IA.

    5. Prompt + Programação + Automação: Um caso real

    Vamos supor que seu cliente quer um sistema que:

    • Recebe um texto do cliente
    • Resume esse texto
    • Salva o resumo em um banco
    • Envia por e-mail

    Você pode fazer tudo isso com Python + Engenharia de Prompt:

    import sqlite3
    import smtplib
    from email.message import EmailMessage
    
    def resumir_texto(texto):
        prompt = f"Resuma o texto abaixo em até 5 linhas, com linguagem clara e objetiva:\n\n{texto}"
        return gerar_resposta(prompt)
    
    def salvar_resumo(no_banco, texto_original, resumo):
        conn = sqlite3.connect(no_banco)
        cursor = conn.cursor()
        cursor.execute('CREATE TABLE IF NOT EXISTS resumos (id INTEGER PRIMARY KEY, original TEXT, resumo TEXT)')
        cursor.execute('INSERT INTO resumos (original, resumo) VALUES (?, ?)', (texto_original, resumo))
        conn.commit()
        conn.close()
    
    def enviar_email(resumo, para_email):
        msg = EmailMessage()
        msg.set_content(resumo)
        msg['Subject'] = 'Resumo Gerado com IA'
        msg['From'] = 'seuemail@exemplo.com'
        msg['To'] = para_email
    
        with smtplib.SMTP('smtp.exemplo.com', 587) as smtp:
            smtp.starttls()
            smtp.login('seuemail@exemplo.com', 'sua_senha')
            smtp.send_message(msg)

    E o fluxo principal:

    texto = input("Cole o texto aqui:\n")
    resumo = resumir_texto(texto)
    salvar_resumo('resumos.db', texto, resumo)
    enviar_email(resumo, 'cliente@exemplo.com')
    print("Resumo enviado com sucesso!")

    Você criou uma solução real de produtividade com IA.

    6. Você não é substituído pela IA. Você comanda a IA.

    O engenheiro de prompt com domínio técnico não é um mero usuário do ChatGPT.

    Ele:

    💡 Pensa como estrategista
    💻 Codifica como desenvolvedor
    🧠 Planeja como arquiteto de soluções
    🔧 Usa a IA como ferramenta de alto nível — não como atalho de preguiçoso

     

  • Como enviar e-mails com o JavaScript usando o EmailJS

    Como enviar e-mails com o JavaScript usando o EmailJS

    Ter um formulário de contato no seu site pessoal ou do seu negócio geralmente é uma boa ideia, afinal de contas, facilita muito o contato das pessoas com você.

    Implementar um formulário no HTML não é muito difícil, mas existe um problemão: como vamos enviar um e-mail a partir daquele formulário?

    Caso você esteja usando um serviço de hospedagem como o Hostgator, Hostinger e afins, talvez você consiga utilizar o servidor PHP destas hospedagens para isso. Pode ser meio chato de configurar, mas funciona.

    Mas quando isso não é possível, nós precisamos de um back-end.

    E como eu sei que você não está afim de fazer um back-end para o seu site só pra isso (até porque você vai ter um outra dor de cabeça pra conseguir hospedar este outro serviço), hoje eu vou te mostrar como usar o EmailJS!

    EmailJS

    Ele vai facilitar bastante este processo.

    Como a própria tela inicial do site já diz, a ideia do EmailJS é que você possa enviar um e-mail diretamente do seu código, sem a necessidade de um servidor. Pois bem, vamos ver então como isso funciona.

    Tela inicial do EmailJS

    Para entender como tudo funciona, vamos começar pela construção de um formulário simples (o código completo do repositório você encontra no final do artigo):

    index.html

    <!DOCTYPE html>
    <html lang="pt-br">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Formulário</title>
      <link rel="stylesheet" href="style.css">
    </head>
    
    <body>
      <form id="form">
        <label for="nome">Nome</label>
        <input type="text" id="nome" name="nome" required>
        <br>
        <label for="email">Email</label>
        <input type="email" id="email" name="email" required>
        <br>
        <label for="mensagem">Mensagem</label>
        <textarea id="mensagem" name="mensagem" required></textarea>
        <input type="submit" value="Enviar">
      </form>
    
      <script src="script.js"></script>
    </body>
    
    </html>

    style.css

    @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
    
    * {
      box-sizing: border-box;
    }
    
    body {
      font-family: "Roboto", serif;
      margin: 0;
      padding: 0;
      background-color: aliceblue;
      width: 100vw;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    #form {
      background-color: #fff;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
      max-width: 400px;
      width: 100%;
    }
    
    #form label {
      display: block;
      margin-bottom: 5px;
      font-weight: bold;
      color: #333;
    }
    
    #form input[type="text"],
    #form input[type="email"],
    #form textarea {
      width: 100%;
      padding: 10px;
      margin-bottom: 15px;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 14px;
      box-sizing: border-box;
    }
    
    #form textarea {
      resize: vertical;
      min-height: 80px;
    }
    
    #form input[type="submit"] {
      background-color: #007BFF;
      color: white;
      padding: 10px 15px;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-size: 16px;
    }
    
    #form input[type="submit"]:hover {
      background-color: #0056b3;
    }
    
    #form input:focus,
    #form textarea:focus {
      border-color: #007BFF;
      outline: none;
      box-shadow: 0 0 4px rgba(0, 123, 255, 0.25);
    }

    script.js

    const form = document.querySelector('#form');
    form.addEventListener('submit', (e) => {
      e.preventDefault();
      console.log("passei aqui!");
    });

    O primeiro passo para usar a ferramenta será inserir o código da biblioteca dentro do nosso projeto. Farei isso usando um CDN:

    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@emailjs/browser@4/dist/email.min.js"></script>

    Agora, antes de continuarmos o código, precisamos de uma API KEY. Essa chave você conseguirá apenas depois de criar sua conta e acessar a área de configurações no site. Será semelhante a esta aqui:

    Chave pública de API utilizada atribuída ao usuário criado no EmailJS

    Com essa chave em mãos, podemos voltar para o nosso script.js e inicializar o serviço:

    emailjs.init({
      publicKey: "A CHAVE DE API AQUI",
    });

    Agora voltaremos pro painel do EmailJS porque precisamos configurar duas outras coisas fundamentais:

    • Um e-mail de serviço (email service);
    • Um template de e-mail (email template).

    O serviço de e-mail será basicamente a configuração da sua conta de e-mail que será usada para o envio dos e-mails. Você consegue usar os principais serviços de e-mail do mercado (Gmail, iCloud, Outlook) ou configurar o próprio servidor SMTP.

    Configuração de um serviço de e-mail na plataforma

    Feito isso, partiremos para o template de e-mail.

    O importante neste template é que você use os campos dinâmicos os com os mesmos nomes que você está usando no seu formulário. Em nosso caso, temos: nomeemail e message. por exemplo:

    Mensagem enviada por: {{name}} <br />
    Email: {{email}} <br />
    Mensagem: {{message}}

    Tanto o seu template quanto o seu serviço possuem identificadores únicos. Precisaremos deles. Agora sim podemos fechar o nosso arquivo JavaScript com o envio do e-mail:

    emailjs.sendForm(ID_DO_SERVICO, ID_DO_TEMPLATE, e.target)
      .then((response) => { alert("Mensagem enviada com sucesso!"); })
      .catch((error) => {
        console.log(error);
        alert("Ocorreu um erro com o envio do seu e-mail");
      });

    O código inteiro ficará semelhante a este:

    const form = document.querySelector('#form');
    form.addEventListener('submit', (e) => {
      e.preventDefault();
    
      emailjs.init({
        publicKey: "hVsyIaGI0Az4LCK_M",
      });
    
      emailjs.sendForm("ID_DO_SERVICO", "ID_DO_TEMPLATE", form)
        .then((response) => alert("Mensagem enviada com sucesso!"))
        .catch((error) => {
          console.log(error);
          alert("Erro ao enviar mensagem!")
        });
    });

    E está pronto! Agora é só esperar o contato da galera 🙂

    Repositório

    https://github.com/Professor-DiegoPinho/email-com-emailjs

    Versão em vídeo

    Confira a versão em vídeo desse artigo!

  • IA: Machine Learning e Deep Learning estão moldando o futuro

    IA: Machine Learning e Deep Learning estão moldando o futuro

    A inteligência artificial (IA) já pode ser considerada uma revolução amplamente adotada por diferentes setores da economia. Um estudo recente da McKinsey & Company, intitulado “The State of AI in Early 2024: Gen AI Adoption Spikes and Starts to Generate Value”, revela que 65% das empresas afirmaram ter utilizado a tecnologia de forma consistente em pelo menos uma área do negócio no último ano, um sinal claro de que a IA deixou de ser tendência para se tornar realidade.

    Machine Learning

    O Machine Learning é uma das engrenagens centrais dessa revolução. Trata-se de um método computacional que permite aos sistemas aprenderem a executar tarefas com base na análise de dados estruturados, como planilhas e banco de dados.

    Em vez de depender de instruções pré-definidas, a tecnologia utiliza modelos matemáticos e estatísticos para reconhecer padrões, prever comportamentos e tomar decisões com mais precisão.

    Dentro desse campo, o aprendizado da IA pode acontecer de duas formas principais. A primeira é o aprendizado supervisionado, amplamente utilizado em tarefas de classificação.

    Nesse modelo, o sistema é treinado com dados previamente rotulados, o que o ajuda a identificar padrões e realizar previsões com maior precisão.

    No mercado financeiro, por exemplo, é possível analisar perfis para concessão de crédito e previsão de fraudes.

    Já no mercado imobiliário, a tecnologia permite estimar o valor de imóveis com base em características semelhantes, como localização, tamanho ou padrão de construção.

    A segunda abordagem é o aprendizado não supervisionado, no qual os dados são agrupados sem rótulos pré-definidos.

    Aqui, o objetivo é identificar estruturas ocultas ou padrões dentro dos dados. Um bom exemplo é o varejo, que utiliza esse método para realizar segmentações mais precisas de clientes com base em hábitos de compra.

    Em telecomunicações, por sua vez, a técnica pode ser aplicada para detectar perfis de uso entre os consumidores, ajudando a antecipar demandas, criar ofertas personalizadas e até reduzir taxas de cancelamento de serviços.

    Deep Learning

    Resumidamente, o Deep Learning é uma subárea mais avançada da IA baseada em redes neurais profundas, estruturas inspiradas no funcionamento do cérebro humano.

    Por isso, a tecnologia é muito utilizada para resolver problemas complexos, como reconhecimento de padrões em imagens, sons e textos.

    O aprendizado no Deep Learning pode ocorrer de forma supervisionada ou não supervisionada, mas um dos métodos mais característicos é o aprendizado por reforço.

    Nesse modelo, o sistema aprende por meio de tentativa e erro, recebendo recompensas ou punições a cada ação tomada.

    É como “educar” uma IA a agir de forma autônoma e a adaptar seu comportamento com base nos resultados obtidos. Essa abordagem é amplamente utilizada em jogos, simulações e robótica.

    Entre as aplicações mais importantes do Deep Learning está o processamento de linguagem natural, essencial para análises comportamentais em plataformas como e-commerces, por exemplo, ao interpretar avaliações de clientes com precisão. Outro campo de destaque é a visão computacional.

    Na área da saúde, a tecnologia tem ajudado médicos a identificar anomalias em exames de imagem, como radiografias e tomografias, contribuindo para diagnósticos mais precoces e assertivos de doenças como o câncer.

    Para onde vamos?

    Fica claro que o Machine Learning e o Deep Learning ajudam a explicar o porquê a IA alcançou o patamar de protagonismo que vemos hoje.

    Essas duas vertentes são fundamentais para compreender como a IA consegue personalizar serviços, automatizar processos e, principalmente, transformar a forma como vivemos e trabalhamos.

    Os grandes modelos de linguagem, como o Chat GPT, Gemini, Claude, DeepSeek e outros, são os principais expoentes da chamada IA generativa, e prova viva desse avanço.

    Presentes em praticamente todos os setores, esses modelos são capazes de executar uma variedade de tarefas com agilidade e precisão. E isso só é possível porque se apoiam em Deep Learning e utilizam o aprendizado por reforço, o que permite evoluir continuamente.

    É por isso que entender esses dois conceitos é essencial para conectar o passado, o presente e o futuro da tecnologia.

    A IA já não é mais uma promessa distante: ela é realidade e, mais do que isso, uma aliada estratégica para que empresas e indivíduos alcancem seus objetivos de forma eficiente.

    No fim do dia, inovação só faz sentido quando gera impacto real no cotidiano. E é justamente essa entrega que o Machine Learning e o Deep Learning tornam possível.

  • Adoção da IA e seu impacto na transição de um desenvolvedor para um criador de software

    Adoção da IA e seu impacto na transição de um desenvolvedor para um criador de software

    Nas últimas duas décadas, testemunhei quase todas as fases da evolução da IA e, no entanto, em nenhum momento acreditei que ela tornaria todos os empregos obsoletos, incluindo o de desenvolvedor de software. Essa perspectiva vem de alguém que introduziu serviços e experiências com tecnologia de IA no mundo todo.

    E ainda assim a pergunta que mais recebi recentemente dos meus alunos de ciência da computação foi: “as ferramentas de IA nos tornarão obsoletos?”. Tive discussões semelhantes com alguns dos meus amigos escritores, imaginando se a IA substituirá totalmente os criadores.

    Minha resposta? “Se alguém usa IA para gerar uma pintura, essa pessoa não é um artista. A menos que ela já tenha as habilidades para criar arte sem a IA.”

    O mesmo se aplica ao desenvolvimento de software. O papel do desenvolvedor não está desaparecendo — ele está evoluindo. Os desenvolvedores que adotarem a IA otimizarão o design, o pensamento sistêmico, a arquitetura e a experiência do usuário de maneiras que a automação sozinha nunca poderia. A IA redefinirá o que significa ser um desenvolvedor, fortalecendo a ideia que eles se tornarão criadores.

    Quando uso a expressão criadores, me refiro àqueles que têm a capacidade de criar algo novo dentro do contexto de tecnologia e negócios. Eles podem ser desenvolvedores de software, designers ou até mesmo indivíduos sem formação técnica.

    Vamos analisar isso profundamente. Os desenvolvedores gastam apenas cerca de duas horas por dia escrevendo código — o resto do tempo é consumido por reuniões ou esperando pelos builds. Sua maior prioridade? Produtividade. Eles querem ferramentas que os ajudem a maximizar seu tempo limitado para escrever códigos.

    Criadores não técnicos, por outro lado, têm uma necessidade semelhante, mas distinta. Eles podem não ser especialistas em escrever código, mas querem a capacidade de criar de forma independente.

    Para eles, soluções como plataformas no code/low code, assistentes de IA e experiências intuitivas de construção são essenciais para desbloquear seu potencial e fazer o trabalho de forma eficiente.

    O futuro da criação — seja para desenvolvedores ou pessoas não técnicas — não é sobre a IA substituindo-os. É sobre a IA permitindo que eles façam mais, mais rápido e com impacto mais significativo.

    IA: um multiplicador de força no desenvolvimento de software

    Assim como uma nova linguagem de código, a IA está se mostrando um formidável multiplicador de força para desenvolvedores. Olhando para trás, ao longo dos anos, linguagens de programação como C já foram a pedra angular do desenvolvimento de software.

    À medida que as linguagens evoluíram para Python, Ruby e Java, muitos previram a necessidade de menos desenvolvedores devido à sua capacidade de simplificar a complexidade significativamente. No entanto essas previsões nunca se materializaram.

    O campo não encolheu; em vez disso, o papel dos desenvolvedores se expandiu, incorporando habilidades de resolução de problemas mais criativas e abstratas.

    Uma evolução semelhante está acontecendo com a IA hoje. Embora a IA possa automatizar tarefas de código de rotina , ela não pode substituir a criatividade de ordem superior e o pensamento sistêmico que desenvolvedores qualificados contribuem.

    Os verdadeiros criadores não são meramente geradores de código — eles são inovadores, arquitetos e estrategistas que são igualmente capazes de navegar pela ambiguidade e influenciar mudanças estratégicas dentro de uma organização.

    Esses criadores empregam uma abordagem interdisciplinar para projetar, construir e gerenciar sistemas complexos.

    Mudança de foco: do código para o design e arquitetura do sistema

    A IA está remodelando o papel dos desenvolvedores, mudando o foco da geração pura de código para o design de sistemas e pensamento arquitetônico. Em sistemas de larga escala, a forma como os componentes e subsistemas interagem é frequentemente mais crítica para o sucesso do que as linhas individuais de código.

    Porém é preciso mudar com foco na confiança, pois os criadores precisam confiar na plataforma em que estão construindo, que deve ser confiável, segura e resiliente para que eles possam se concentrar na inovação sem se preocupar com falhas; simples, já que a produtividade é a principal prioridade do desenvolvedor e os melhores sistemas removem atrito, encurtam o tempo de produção e abstraem a complexidade, tornando mais fácil construir e escalar; e inteligentes, a fim de aproveitar a IA e os dados contextuais para reduzir o tempo, aprimorar as experiências e automatizar a complexidade, ajudando os desenvolvedores a se moverem mais rápido e a criar soluções mais intuitivas e impactantes.

    Esta é a essência do pensamento sistêmico — ir além de ferramentas fragmentadas e soluções pontuais para uma plataforma coesa e conectada que permite que os criadores inovem mais rápido e com maior impacto. A IA pode aumentar a produtividade, mas o núcleo do desenvolvimento de software — design, arquitetura e experiência do usuário — continua distintamente humano.

    Os novos criadores softwares

    O futuro do desenvolvimento de software é sobre os desenvolvedores evoluírem para criadores estratégicos e orientados pela experiência, que entendem a tecnologia, validam seu trabalho e sempre mantêm o cliente no centro de seu trabalho.

    A evolução do desenvolvimento de software exige maior ênfase na experiência do usuário, habilidades de teste mais fortes, implementação estratégica de IA e, acima de tudo, um profundo entendimento dos clientes e da tecnologia que eles estão usando.

    Nem todos os criadores escrevem código, mas todos eles criam. Seja você um profissional de marketing, gerente de produto, designer ou empreendedor, a capacidade de construir e dar vida a ideias está mais acessível do que nunca. A ascensão da IA, automação e plataformas no code/low code está remodelando como criadores  não técnicos criam, inovam e geram impacto. Então, quais habilidades serão essenciais para construtores não técnicos neste cenário em evolução?

    A ascensão da IA e da automação não significa que apenas desenvolvedores podem construir — significa que qualquer um com a mentalidade e as habilidades certas pode. A próxima geração de criadores vai misturar criatividade com curiosidade técnica, pensamento estratégico com insights de dados e eficiência orientada por IA com intuição humana.

    A IA deve ser alavancada para aumentar a produtividade, mas nunca deve definir o trabalho em si — a verdadeira inovação vem de saber quando confiar na automação e quando aplicar o julgamento humano. O futuro é sobre capacitar os criadores a criar mais, inovar mais rápido e ultrapassar os limites do que é possível. A IA continuará a mudar a forma como construímos, mas a essência da criação — a capacidade de pensar, projetar e resolver problemas — sempre pertencerá a nós. E se você realmente quer se tornar um artista, pegue seu pincel e vamos lá!

    *Inbal Shani é Chief Product Officer e lidera a organização de P&D da Twilio – texto adaptado.

     

  • Fim do suporte ao Windows 10: riscos e soluções para gerir a mudança

    Fim do suporte ao Windows 10: riscos e soluções para gerir a mudança

    Após o dia 14 de outubro deste ano de 2025, a Microsoft vai encerrar o suporte ao Windows 10 – o que significa que o sistema operacional não vai mais receber atualizações de segurança, ou suporte do fabricante.

    Com uma grande base instalada, essa versão do sistema operacional serviu de pilar para inúmeras aplicações corporativas e integrações de TI, especialmente em ambientes de grande porte que dependem de consistência e estabilidade para rodar serviços críticos.

    Agora, a proximidade do fim do suporte oficial representa um marco que exige atenção imediata: manter máquinas nesse sistema pode abrir brechas para ameaças cada vez mais sofisticadas, além de impactar a produtividade e a conformidade regulatória.

    Quem acompanha o setor de TI sabe que essas descontinuações já ocorreram antes, como no caso do Windows 7, mas o cenário atual é ainda mais complexo.

    Windows 10

    A evolução rápida das ciberameaças, a intensificação da transformação digital e a adoção ampliada do trabalho híbrido tornam qualquer vulnerabilidade potencialmente perigosa, seja para grandes corporações ou para grupos que lidam com dados sensíveis.

    Ao mesmo tempo, muitas empresas brasileiras ainda operam com um grande parque de máquinas que não será compatível com o Windows 11 – seja pela ausência de componentes mínimos de hardware, seja pela falta de um plano efetivo de migração.

    O grande problema é que ficar no Windows 10 depois de outubro é abrir espaço para silos de ameaças ocultas. A partir do momento em que a Microsoft encerrar as atualizações de segurança, cada nova vulnerabilidade descoberta deixará de ser corrigida.

    Em um ambiente corporativo, esse risco se multiplica, pois máquinas sem patches podem se tornar a porta de entrada para ataques de ransomware, sequestro de dados, sabotagens e uma série de incidentes que podem paralisar a operação, com perdas diretas e indiretas elevadas.

    Um cenário de vulnerabilidades e riscos crescentes

    O fim do suporte do Windows 10 significa, na prática, que serão suspensas as correções de falhas e as melhorias de segurança liberadas mensalmente. Cibercriminosos tendem a focar seus ataques justamente em versões desatualizadas de sistemas operacionais, pois sabem que não haverá barreiras técnicas novas para impedir suas investidas.

    Além dos riscos imediatos de segurança, há também a questão de governança e compliance. Diversos setores regulados, como financeiro, saúde e varejo, possuem diretrizes rígidas em relação à proteção de dados e à garantia de atualizações constantes.

    Manter máquinas em um sistema sem suporte oficial pode acarretar multas e sanções, caso seja interpretado como negligência perante regras de proteção de dados (como a LGPD, no caso brasileiro), ou perante padrões internacionais de segurança. Essa lacuna pode, inclusive, refletir na reputação da empresa e na confiança de investidores e parceiros de negócio.

    Outro problema, menos óbvio mas igualmente importante, é a fragmentação operacional. A manutenção de um parque de máquinas defasado cria cenários em que cada setor da empresa tenta compensar a falta de atualizações de maneiras diversas – seja instalando softwares de segurança de terceiros, seja adotando soluções temporárias para contornar problemas de incompatibilidade.

    Esse tipo de improviso resulta em um ambiente de TI ainda mais complexo, em que há pouca visibilidade sobre o que está realmente seguro e atualizado. E, quando não há um plano centralizado de migração, cada departamento segue um ritmo diferente, o que gera atrasos, custos extras e riscos de incompatibilidades entre sistemas internos.

    A corrida contra o tempo e a pressão orçamentária

    A proximidade do fim do suporte impõe um senso de urgência à liderança. Afinal, estamos falando de uma transformação que, em muitos casos, envolve centenas ou até milhares de máquinas.

    Não basta apenas comprar novas licenças ou realizar o upgrade in-place: há a necessidade de avaliar a compatibilidade de hardware, a maturidade dos aplicativos que rodarão no novo sistema operacional, as políticas de segurança e criptografia (como a exigência do TPM 2.0, por exemplo) e, principalmente, o treinamento e adaptação das equipes que usarão diariamente essas máquinas.

    O grande desafio é equilibrar essa pressão com o orçamento disponível. Se, por um lado, há urgência em abandonar o Windows 10, por outro, a substituição de um parque de dispositivos pode significar um desembolso considerável.

    Muitas empresas se veem, portanto, em uma espécie de encruzilhada: sabem que migrar para o Windows 11 é indispensável para garantir segurança e performance, mas temem pelo impacto financeiro imediato de renovar máquinas que ainda funcionam “razoavelmente bem” no dia a dia.

    A experiência mostra, porém, que adiar esse movimento tende a sair ainda mais caro. A própria Microsoft e parceiros especializados já alertaram para programas de suporte estendido (pagos) que só retardam o inevitável, além de onerar o caixa da empresa com custos recorrentes e crescentes.

    Enquanto isso, cibercriminosos não vão aguardar a formação de um consenso. Cada mês em que o Windows 10 permanece sem updates oficiais é um mês de oportunidades para ataques direcionados.

    Em certas negociações de seguros cibernéticos, inclusive, contar com sistemas obsoletos pode inviabilizar a contratação ou encarecer muito os prêmios. Logo, a decisão de postergar a transição acaba gerando gastos que superam os custos de um planejamento de migração bem estruturado.

    Tecnologia

    Uma opção para lidar com o desafio orçamentário é avaliar o modelo de investimento em tecnologia.

    Nesse sentido, existem basicamente dois caminhos: ou a empresa recorre ao Capex (Capital Expenditure), adquirindo novos equipamentos por meio de investimentos de capital – o que pode ser oneroso em épocas de alta do dólar e dos juros –, ou, então, opta pelo Opex (Operational Expenditure), contratando o hardware como serviço (outsourcing).

    No primeiro cenário (Capex), há a necessidade de um desembolso elevado para compra de notebooks e desktops, impactando o fluxo de caixa da organização.

    Já no modelo Opex, os custos são diluídos em despesas operacionais contínuas, o que se mostra vantajoso para muitas empresas e órgãos públicos, pois minimiza a demanda de capital inicial e reduz o risco associado a obsolescências futuras.

    O modelo Opex – que em resumo, é o outsourcing – possibilita as empresas contarem com suporte especializado, atualizações recorrentes e a possibilidade de escalar ou reduzir o parque de máquinas conforme a demanda, sem precisar arcar com a substituição completa dos equipamentos.

    Esse modelo traz mais previsibilidade no planejamento financeiro, mantendo a infraestrutura em constante evolução e em conformidade com as exigências do Windows 11 e das boas práticas de segurança.

    As múltiplas opções para evitar gargalos

    Diante desse cenário, há diferentes caminhos para as empresas que querem se preparar com antecedência:

    Upgrade do sistema operacional: 

    Em muitas máquinas compatíveis, basta realizar a migração do Windows 10 para o Windows 11, seguindo as boas práticas de backup, checagem de drivers e testes de compatibilidade com sistemas críticos. Essa é a rota mais direta para quem comprou equipamentos relativamente recentes, que já contam com o módulo TPM 2.0 e outras exigências do Windows 11.

    Renovação do parque de hardware: 

    No caso de dispositivos que não atingem os requisitos mínimos, a substituição do equipamento pode ser a melhor escolha. Embora a aquisição de novos computadores represente um custo imediato, garante mais longevidade de uso e uma plataforma mais robusta para rodar aplicações modernas, além de funcionalidades de segurança baseadas em hardware. Muitas vezes, as empresas aproveitam esse movimento para padronizar as configurações internas, diminuindo o retrabalho de suporte e manutenção.

    Adoção de plataformas de virtualização e Desktop as a Service (DaaS): 

    Outra tendência é migrar parte das operações de TI para desktops virtuais, rodando na nuvem. Isso permite que usuários acessem um ambiente Windows 11 a partir de máquinas menos robustas, desde que haja boa conectividade. Embora não seja a solução para todos os casos, pode ser um caminho viável para workloads específicos ou para empresas que preferem um modelo de custo previsível, sem imobilizar tanto capital na compra de novos equipamentos.

    Parcerias estratégicas e consultoria especializada: 

    A escolha de um parceiro de tecnologia confiável pode encurtar caminhos e oferecer a experiência de quem já enfrentou transições semelhantes em outras organizações. Avaliar a estrutura atual, criar um cronograma de migração escalonada e planejar contingências para máquinas críticas são passos que exigem conhecimento técnico e visão de negócio. Em muitos casos, é mais econômico contratar uma consultoria para executar esse processo de forma ágil e estruturada, do que tentar conduzir tudo internamente e só depois correr atrás de suporte ao surgirem problemas.

    Segurança da informação como eixo central

    Independentemente do caminho escolhido, a segurança da informação deve ser o eixo central de todo o planejamento. Não estamos falando apenas de instalar antivírus ou atualizar políticas de firewall, mas de construir uma governança sólida.

    A descontinuação do Windows 10 pode ser uma oportunidade para rever processos internos e adotar conceitos mais avançados de proteção, como o Zero Trust, que exige verificação constante de usuários e dispositivos para conceder acesso a recursos da empresa.

    O ideal é que as empresas definam diretrizes claras de segurança e conformidade, mapeando quem tem acesso a cada aplicação e quais dados precisam de maior nível de proteção.

    É nesse contexto que a parceria com provedores de segurança digital, integradores ou consultorias especializadas se torna ainda mais relevante. Quando o assunto é ameaça cibernética, não basta assumir que tudo está protegido porque “sempre funcionou assim”.

    Se a organização não fizer uma checagem profunda de configurações, não estabelecer monitoramento contínuo e não mantiver suas máquinas no estado mais atualizado possível, rapidamente surgirá alguma brecha para invasores explorarem.

    O fato é que postergar a migração do Windows 10 não elimina a necessidade de mudança. Pelo contrário, amplia o risco de brechas de segurança, prejudica a conformidade regulatória e pode minar a competitividade das empresas brasileiras, que já lidam com diversos desafios estruturais na economia.

    O caminho para evitar esse gargalo é encarar o fim do suporte como uma oportunidade de evolução e fortalecimento da estratégia de TI, seja investindo na compra de equipamentos mais atuais, seja migrando para uma plataforma de virtualização ou, ainda, contando com um parceiro de tecnologia para garantir que tudo aconteça de forma planejada e eficaz. ♦


    LEIA TAMBÉM

     

  • Explorando o Padrão CQRS em APIs Web com .NET Core

    Explorando o Padrão CQRS em APIs Web com .NET Core

    Introdução ao Padrão CQRS

    O padrão Command Query Responsibility Segregation (CQRS) é uma abordagem arquitetural que separa as operações de leitura e escrita em uma aplicação. Essa separação permite otimizar cada operação de forma independente, levando a uma melhor escalabilidade e desempenho. Em vez de ter um modelo de dados unificado, o CQRS propõe que as operações de escrita (comandos) e leitura (consultas) sejam tratadas de maneiras distintas (RICHTER, 2024).

    O CQRS é especialmente útil em aplicações complexas e de grande escala, onde a lógica de negócios pode ser intensiva e as operações de leitura podem ser otimizadas de forma diferente das operações de gravação (RIBEIRO, 2024). Neste artigo, vamos explorar como implementar CQRS em APIs Web utilizando .NET Core, abordando conceitos, componentes, e exemplos práticos para facilitar a compreensão da implementação.

    Origem do CQRS

    O CQRS é um padrão que surgiu como uma extensão do padrão de arquitetura de microserviços, visando resolver alguns dos desafios que surgem quando se tenta escalar aplicações que realizam tanto operações de leitura quanto de escrita (AL FANSHA et al., 2021). A ideia central do CQRS é dividir as responsabilidades de leitura e escrita, permitindo que cada uma delas seja otimizada de maneira independente (RIBEIRO, 2024).

    Essa abordagem promove uma melhor organização do código, uma vez que as partes do sistema que lidam com a leitura de dados não precisam se preocupar com a lógica de escrita, e vice-versa. Além disso, o CQRS permite que diferentes tecnologias sejam utilizadas para leitura e escrita, aproveitando as melhores práticas e ferramentas disponíveis para cada operação.

    O CQRS é particularmente vantajoso em cenários onde a aplicação precisa lidar com altos volumes de dados e um grande número de usuários simultâneos (CHERIF et al., 2024). A separação de comandos e consultas não apenas melhora a performance, mas também facilita a manutenção e a evolução do sistema ao longo do tempo.

    Componentes Básicos do CQRS

    Em uma arquitetura CQRS, geralmente lidamos com três componentes principais: comandos, consultas e eventos. Vamos detalhar cada um deles:

    • Comandos: São operações que alteram o estado da aplicação. Cada comando deve ser tratado de forma assíncrona para garantir que a aplicação possa continuar a responder a outras requisições enquanto aguarda a conclusão da operação.
    • Consultas: São solicitações que recuperam dados do sistema sem alterar seu estado. As consultas podem ser otimizadas para fornecer resultados rápidos e eficientes.
    • Eventos: Representam mudanças que ocorreram no sistema e podem ser utilizados para notificar outros componentes ou sistemas. Eventos são fundamentais para implementar a comunicação entre diferentes partes do sistema e podem facilitar a integração com outros serviços externos.

    Estrutura de um Projeto .NET Core com CQRS

    Para ilustrar a atuação do padrão CQRS, vamos considerar um projeto básico em .NET Core. Utilizaremos o ASP.NET Core Web API. O design de implementação ficará dessa forma:

    
    +-----------------------------------------------------+
    |                                                     |
    |                     MyCQRSApp                       |
    |                                                     |
    +------+---------------------------------------+------+
           |                                       |
           |                                       |
    +------v------+                         +------v------+
    |  Command    |                         |  Get        |
    |  Actions    |                         |  Actions    |
    +------+------+                         +------+------+
           |                                       |
           |                                       |
    +------v------+     +-------------+     +------v------+
    |  Command    |     |  [Producer] |     |  Query      |
    |    Bus      +----->  Async      |     | (IQueryable)|
    |             |     |  Messages   |     |             |
    +-------------+     +-------------+     +------+------+
           |                                       |
           |                                       |
    +------v------+                     +----------v------+
    |  Write DB   |                     |  Read DB        |
    |  (Event     |                     |  (Projection/   |
    |  Sourcing)  |                     |  Read Database) |
    +-------------+                     +-----------------+
    

     

    Abaixo a estrutura do projeto:

    MyCQRSApp
    ¦
    +-- Application
    ¦   +-- Commands
    ¦   ¦   +-- CreateProductCommand.cs
    ¦   ¦   +-- CommandHandlers
    ¦   ¦       +-- CreateProductCommandHandler.cs
    ¦   +-- Queries
    ¦   ¦   +-- GetProductQuery.cs
    ¦   ¦   +-- QueryHandlers
    ¦   ¦       +-- GetProductQueryHandler.cs
    ¦   +-- Events
    ¦       +-- ProductCreatedEvent.cs
    ¦
    +-- Infrastructure
    ¦   +-- Bus
    ¦   ¦   +-- CommandBus.cs
    ¦   ¦   +-- EventBus.cs
    ¦   +-- Persistence
    ¦   ¦   +-- ProductService.cs
    ¦   ¦   +-- ProductRepository.cs
    ¦   +-- Messaging
    ¦       +-- IEventBus.cs
    ¦       +-- ICommandBus.cs
    ¦       +-- InMemoryEventBus.cs
    ¦
    +-- API
    ¦   +-- Controllers
    ¦       +-- ProductsController.cs
    ¦
    +-- Domain
        +-- Models
            +-- Product.cs

    Implementando Comandos

    O padrão CQRS (Command Query Responsibility Segregation) sugere separar as operações de leitura (queries) das operações de escrita (commands). Vamos começar implementando os comandos, que representam ações ou mudanças de estado que queremos realizar em nosso sistema. Cada comando é uma solicitação para executar uma ação, como criar ou atualizar um recurso. No exemplo a seguir, criaremos um comando para adicionar um produto:

    public class CreateProductCommand
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
    }

    O comando CreateProductCommand contém as propriedades necessárias para criar um produto, como nome, preço e quantidade. Agora, precisamos de um manipulador de comando, que será o responsável por processar esse comando e executar a lógica de negócios associada.

    O manipulador de comando será responsável por instanciar o produto, adicionar o mesmo ao banco de dados e, em seguida, disparar um evento para notificar que o produto foi criado. Veja como isso funciona:

    public class CreateProductCommandHandler : ICommandHandler
    {
        private readonly ProductService _productService;
        private readonly IEventBus _eventBus; // Event bus para publicar eventos
    
        public CreateProductCommandHandler(ProductService productService, IEventBus eventBus)
        {
            _productService = productService;
            _eventBus = eventBus;
        }
    
        public async Task Handle(CreateProductCommand command)
        {
            var product = new Product 
            {
                Name = command.Name,
                Price = command.Price,
                Quantity = command.Quantity
            };
    
            await _productService.AddProductAsync(product);
    
            // Publica o evento após a criação do produto
            var productCreatedEvent = new ProductCreatedEvent(product.Id, product.Name);
            await _eventBus.PublishAsync(productCreatedEvent);
        }
    }

    CreateProductCommandHandler recebe o comando, cria um novo objeto Product e o adiciona ao banco de dados utilizando o serviço ProductService. Após a criação, um evento chamado ProductCreatedEvent é disparado, notificando outras partes do sistema que o produto foi criado.

    O evento ProductCreatedEvent carrega as informações necessárias para notificar o sistema de que um produto foi criado com sucesso. Esse evento pode ser assinado por outros componentes do sistema para executar ações subsequentes, como atualizar caches, enviar notificações ou registrar logs.

    Implementando Consultas

    O próximo passo está em implementar as consultas. Ao contrário dos comandos, que alteram o estado do sistema, as consultas são responsáveis por recuperar dados. Vamos criar um exemplo de consulta para obter as informações de um produto específico a partir de seu ID.

    public class GetProductQuery
    {
        public int ProductId { get; set; }
    
        public GetProductQuery(int productId)
        {
            ProductId = productId;
        }
    }

    O comando GetProductQuery contém o ID do produto que estamos buscando. Agora, precisamos de um manipulador de consulta, que será o responsável por buscar as informações do produto.

    public class GetProductQueryHandler
    {
        private readonly ProductService _productService;
    
        public GetProductQueryHandler(ProductService productService)
        {
            _productService = productService;
        }
    
        public async Task Handle(GetProductQuery query)
        {
            return await _productService.GetProductByIdAsync(query.ProductId);
        }
    }

    GetProductQueryHandler recebe o comando de consulta e usa o serviço ProductService para recuperar o produto correspondente ao ID fornecido. Essa consulta pode ser otimizada com técnicas como cache, dependendo das necessidades do sistema.

    Controladores de API

    Com os comandos e consultas implementados, o próximo passo está em criar os controladores de API para expor essas operações via HTTP. Abaixo, um controlador para os produtos, com endpoints para criar e obter produtos.

    [ApiController]
    [Route("api/[controller]")]
    public class ProductsController : ControllerBase
    {
        private readonly ICommandBus _commandBus;  // Barramento de comandos
        private readonly IQueryHandler _getProductHandler;
    
        public ProductsController(ICommandBus commandBus, IQueryHandler getProductHandler)
        {
            _commandBus = commandBus;
            _getProductHandler = getProductHandler;
        }
    
        [HttpPost]
        public async Task CreateProduct([FromBody] CreateProductCommand command)
        {
            // Envia o comando para o barramento de comandos
            await _commandBus.SendAsync(command);
            return Ok();
        }
    
        [HttpGet("{id}")]
        public async Task GetProduct(int id)
        {
            var query = new GetProductQuery(id);
            var product = await _getProductHandler.Handle(query);
            return Ok(product);
        }
    }

    O controlador ProductsController expõe dois endpoints: um para criar produtos com o método POST e outro para consultar produtos com o método GET. O controlador interage com os barramentos de comandos e consultas para delegar as operações adequadas.

    Gerenciamento de Eventos

    O CQRS também é frequentemente usado em conjunto com eventos, onde a execução de um comando dispara um evento correspondente. Esses eventos podem ser usados para notificar outras partes do sistema sobre alterações de estado. No exemplo abaixo, vamos criar um evento ProductCreatedEvent, que será disparado após a criação de um produto.

    public class ProductCreatedEvent
    {
        public int ProductId { get; private set; }
        public string Name { get; private set; }
    
        public ProductCreatedEvent(int productId, string name)
        {
            ProductId = productId;
            Name = name;
        }
    }

    Este evento contém informações sobre o produto criado, como seu ID e nome. Após a criação do produto, o evento será publicado para que outros componentes do sistema possam reagir a essa mudança de estado, como atualizar caches, enviar notificações ou realizar outras ações de integração.

    A publicação e assinatura de eventos podem ser gerenciadas utilizando bibliotecas como MediatR, RabbitMQ, Azure Service Bus ou outras soluções baseadas em mensageria. O uso de eventos melhora a escalabilidade do sistema, permitindo que ele reaja de forma mais dinâmica e flexível a mudanças no estado do sistema.

    Desafios e Considerações ao Implementar CQRS

    Apesar das vantagens do CQRS, é importante estar ciente de alguns desafios que podem surgir ao implementá-lo. A complexidade adicional que o CQRS traz pode ser um obstáculo, especialmente em projetos menores ou em equipes com menos experiência na abordagem. A gestão de estados e a sincronia entre os componentes de leitura e escrita podem se tornar complicadas, exigindo um bom planejamento e uma arquitetura bem definida.

    É essencial ter uma comunicação clara entre os membros da equipe para garantir que todos entendam as responsabilidades e como cada componente interage com os outros. Além disso, é recomendável ter um bom monitoramento e logging em produção para detectar problemas rapidamente.

    Conclusão

    O padrão CQRS oferece uma maneira poderosa de estruturar aplicações complexas, separando as preocupações de leitura e escrita. Ao implementar CQRS em uma aplicação .NET Core, você pode criar APIs mais escaláveis, flexíveis e de alto desempenho. Embora a implementação do CQRS possa adicionar complexidade, os benefícios em aplicações de grande escala frequentemente superam esses desafios.

    No final, a adoção do CQRS deve ser uma decisão informada, baseada nas necessidades específicas do seu projeto. Com a prática e a experiência adequadas, você pode aproveitar ao máximo esse padrão e construir aplicações que atendam às crescentes demandas do mercado atual.

    Referências

    • RICHTER, Jens. Performance Impact of the Command Query Responsibility Segregation (CQRS) Pattern in C# Web APIs. 2024. Tese de Doutorado. Universitäts-und Landesbibliothek Sachsen-Anhalt.
    • AL FANSHA, Difa; SETYAWAN, Muhammad Yusril Helmi; FAUZAN, Mohamad Nurkamal. Load Test pada Microservice yang menerapkan CQRS dan Event Sourcing. Jurnal Buana Informatika, v. 12, n. 2, p. 126-134, 2021.
    • CHERIF, Ayman NAIT et al. CQRS and Blockchain with Zero-Knowledge Proofs for Secure Multi-Agent Decision-Making. International Journal of Advanced Computer Science & Applications, v. 15, n. 11, 2024.
    • RIBEIRO, Eduardo Renani. Alternativas para consistência eventual em um sistema no padrão CQRS. 2024.
  • Gerenciar vários projetos tech ao mesmo tempo é como viver numa sequência de montanhas-russas

    Gerenciar vários projetos tech ao mesmo tempo é como viver numa sequência de montanhas-russas

    Gerenciar um projeto de tecnologia já é uma montanha-russa. Agora imagine dar dispatch em cinco ao mesmo tempo, cada uma com seu looping, urgência e trilho próprio. É adrenalina em tempo real. E se você também vive a realidade dos prazos apertados, escopos flutuantes e times diversos, sabe que organização e método não são luxo,  são sobrevivência.

    Aqui compartilho o que funciona pra mim quando tudo parece acontecer… ao mesmo tempo.

    Rituais curtos e frequentes: constância vence complexidade

    Reuniões longas? Só se for em casa com a família. Sou fã de rituais rápidos e objetivos. Por exemplo, toda segunda-feira às 9h eu faço uma daily estendida com líderes de projeto: 15 minutos para status, 10 para alertas e uma rodada de “tem alguma bomba vindo aí?”

    Esse tempo curto nos força a priorizar, mas mais importante: mantém o hábito vivo. Se o ritual for longo e cansativo, ele some da rotina. Já vi muita reunião nascer animada e desaparecer em 3 semanas.

    Radar de riscos: o problema é o que você não vê

    Projetos não costumam desandar de repente, eles sussurram antes de gritar. Uma vez, um Dev começou a mandar updates cada vez mais genéricos tipo “tudo indo”, “só finalizando”.

    No terceiro “finalizando”, fui puxar e descobri que a entrega estava 80% parada por causa de uma dependência que ninguém tinha avisado.

    Criei uma planilha de sinais: coisas pequenas que merecem olhar de perto. E mais que isso: me treinei para prestar atenção nas entrelinhas.

    Pessoas: gestão é feita de gente, não só de tarefa

    Cada pessoa tem seu jeito e isso muda tudo. Tem quem precise de autonomia total. Tem quem trava se não tiver o norte claro. E tem os que só funcionam depois do segundo café (me identifico rs).

    Além da técnica, tento entender o que motiva, o que trava, o que acelera. Às vezes, uma escuta de 5 minutos muda o clima de uma semana inteira. E quando rola uma parceria real, o projeto anda muito melhor.

    Templates e boas práticas: reinventar só quando precisa

    Minha pasta de templates tem de tudo: cronograma em Gantt, kick-off de projeto, ata de reunião com emoji (sim!), e uma planilha mágica de orçamento que calcula até margem de erro.

    Claro que personalizo quando necessário. Mas ter essa base me faz ganhar horas preciosas e ainda passa aquela imagem de quem já sabe o caminho.

    Delegar com confiança e estratégia

    Delegar não é largar, é acertar a mão na entrega certa, pra pessoa certa, no momento certo. Uma vez pedi a um analista pra cuidar de uma apresentação para cliente. Ele entregou algo além do esperado e virou meu ponto de apoio pra toda parte visual dali em diante (e sim, ele estava de acordo com isso porque era algo que curtia fazer).

    Eu supervisiono, mas não travo. Delegar bem é fazer o time crescer e você respirar.

    Negociar prioridades: ninguém gosta de ouvir não (mas adora um bom acordo)

    Todo mundo acha que seu projeto é o mais urgente. E tudo bem, faz parte. Mas quando o recurso é limitado, o “não” vira inevitável. O que eu tento sempre fazer é propor um ganha-ganha.

    Uma vez um cliente queria lançar um módulo novo em 2 semanas. Isso não daria a qualidade que precisávamos, então propus entregarmos o núcleo funcional nessa data, e o restante em duas waves seguintes com direito a demo e material de onboarding. Resultado? Ele ficou feliz com o controle do cronograma, qualidade e ainda ganhou entregas visíveis ao longo do tempo.

    Meu portifólio de projetos eu chamos de meu Waze

    Não dá pra jogar xadrez de olhos vendados. Ter meu portfólio visualmente organizado me dá paz e poder de decisão. Uso cores, códigos e dashboards que me mostram onde está o risco, o que vai travar e onde posso respirar.

    É como ter um Waze dos projetos: você ainda vai pegar trânsito, mas ao menos sabe onde está e qual a melhor rota.

    No fim do dia, sigo no carrinho

    Gerenciar vários projetos ao mesmo tempo não é sobre fazer tudo. Mas é sobre criar sistemas e relações que funcionam mesmo quando o dia aperta. É entender de gente, negociar com clareza, manter o radar ligado e, às vezes, ajustar a si mesmo primeiro, no meio do caos.

    Porque, no fim das contas, todos estamos ali, no mesmo carrinho da montanha-russa. O segredo está em saber a hora de acelerar, de frear, de fechar os olhos… e, principalmente, de curtir a vista quando ela aparece.

    Se entregou, aprendeu e ainda terminou o dia com o time engajado… Pode respirar, o carrinho voltou inteiro, entregue, e com histórias pra contar na estação dessa montanha-russa.

     

     

     

     

     

  • UX e Código: Por que designers que conhecem programação têm uma vantagem estratégica

    UX e Código: Por que designers que conhecem programação têm uma vantagem estratégica

    No mundo da Experiência do Usuário (UX) e da Interface do Usuário (UI), a principal missão é criar produtos digitais intuitivos, funcionais e agradáveis para os usuários. Mas para atingir esse objetivo com excelência, é preciso olhar além das interfaces — e mergulhar também nos bastidores técnicos das soluções digitais. Cada vez mais, conhecer linguagens de programação (sejam de front-end ou back-end) se torna um diferencial significativo para profissionais de UX/UI.

    Não se trata de abandonar o design para virar dev. Mas sim de expandir a visão, aumentar a empatia com o time técnico e propor soluções mais realistas, sustentáveis e eficientes. Neste artigo, vamos explorar como o conhecimento em programação soma às competências de UX/UI — e por que essa interseção pode ser o futuro da prática em design digital.

    1. Empatia técnica: entender para colaborar melhor

    A empatia sempre foi um dos pilares do design centrado no usuário. Mas ela não deve estar presente apenas na relação com quem usa o produto — ela precisa se estender também ao time de desenvolvimento.

    Quando um designer entende os fundamentos de HTML, CSS, JavaScript, ou mesmo lógica de back-end com Python, Java ou Node.js, ele passa a:

    • Compreender as limitações técnicas e os trade-offs envolvidos em uma funcionalidade;
    • Saber o que é simples ou complexo de implementar;
    • Negociar e propor alternativas viáveis sem comprometer a experiência do usuário.

    Essa fluência mútua entre design e desenvolvimento facilita a colaboração, reduz ruídos na comunicação e acelera a entrega de soluções mais bem pensadas.

    “Quando um designer entende como o código funciona, ele não desenha sonhos impossíveis. Ele propõe ideias que podem ser construídas de verdade.” — Dan Mall, design director e educador em design systems.

    2. UX mais próximo do MVP (Produto Mínimo Viável)

    Profissionais de UX/UI que conhecem programação conseguem contribuir de forma mais estratégica na construção de MVPs. Ao compreender como funcionam os ciclos de desenvolvimento, integrações com APIs, estrutura de banco de dados ou mesmo o funcionamento de frameworks front-end como React ou Vue, eles têm:

    • Mais clareza para definir o que realmente é essencial no primeiro release;
    • Facilidade para ajustar fluxos e protótipos à realidade técnica do projeto;
    • Propriedade para dialogar com Product Managers e Tech Leads sobre escopo, complexidade e priorização de features.

    O resultado? Soluções mais enxutas, funcionais e validadas rapidamente com os usuários.

    3. Melhor uso de componentes e design systems

    Design Systems e bibliotecas de componentes se tornaram parte do cotidiano de times de produto. E para que designers usem esses sistemas com inteligência, é fundamental que compreendam como os componentes são codificados, reaproveitados e combinados.

    Conhecimento básico em linguagens como HTML e CSS permite que designers:

    • Evitem criar componentes redundantes ou difíceis de manter;
    • Respeitem padrões técnicos e visuais já existentes;
    • Trabalhem com maior sinergia com desenvolvedores front-end.

    Isso reduz o retrabalho, garante mais consistência visual e promove uma cultura de design sustentável.

    4. Prototipação funcional e testes mais reais

    Designers com noções de JavaScript ou frameworks como Framer Motion, por exemplo, conseguem criar protótipos interativos e animados mais próximos do produto real — o que gera:

    • Testes de usabilidade mais precisos;
    • Comunicação visual mais clara com stakeholders e devs;
    • Mais confiança para validar microinterações e fluxos dinâmicos.

    Plataformas como Framer, Webflow e Figma Dev Mode têm crescido justamente por permitir que designers interajam com camadas de código — mesmo sem serem desenvolvedores experientes.

    5. Maior empregabilidade e visão de produto

    No cenário competitivo atual, as empresas valorizam profissionais multidisciplinares. Designers que “falam a linguagem dos devs” ganham:

    • Destaque em processos seletivos, especialmente em startups ou squads enxutos;
    • Mais facilidade para liderar iniciativas de UX com visão holística do produto;
    • Capacidade de migrar para áreas como Product Design, Service Design ou até mesmo se tornar Tech Leads em DesignOps.

    “O futuro do design digital está na interseção entre forma, função e tecnologia. Designers que entendem código têm muito mais impacto no produto final.” — Julie Zhuo, ex-VP de Produto do Facebook.

    6. Aprender código não precisa ser assustador

    Muitos designers acreditam que aprender programação é um território hostil. Mas hoje existem dezenas de plataformas e cursos voltados especificamente para designers, com uma didática amigável e aplicável ao dia a dia de UX/UI. Algumas recomendações:

    • Alura (onde sou Embaixador) – com cursos voltados à integração entre design e desenvolvimento;
    • Dio (onde escrevo artigos) – milhares de cursos e bootcamps sobre diversas linguagens;
    • Codecademy – ideal para quem quer começar do zero;
    • Frontend Mentor – prática de HTML/CSS com desafios reais;
    • Web.dev – recursos oficiais do Google voltados à performance e acessibilidade.

    O importante é começar aos poucos, com curiosidade e sem pressão. Aprender programação não vai te transformar em dev, mas vai te tornar um designer mais completo, empático e preparado para o mercado.

    7. UX e programação — a combinação que transforma produtos

    Conhecer programação não significa abandonar a essência do design, nem deixar de lado a sensibilidade estética ou a empatia com os usuários. Pelo contrário: significa ampliar o repertório, colaborar melhor com os times de produto e transformar ideias em soluções reais com mais consistência.

    Design e tecnologia caminham juntos. E quando UX/UI se conecta ao código, o resultado é um produto mais viável, eficiente e centrado nas pessoas — do começo ao fim.

    Se você é designer e ainda não deu seus primeiros passos no mundo da programação, minha dica é: comece hoje. Um comando aqui, um componente ali… e você verá como a linguagem do código pode ser, também, uma linguagem do design.

    Quer trocar ideia sobre isso ou compartilhar sua experiência? Me chama — vai ser um prazer continuar essa conversa. Você me acha por aí no Linkedin ou na plataforma de mentorias ADPList.org. 🚀♦


    LEIA TAMBÉM

     

  • LEIA-ME ou te devoro: Como escrever um bom README

    LEIA-ME ou te devoro: Como escrever um bom README

    Que título dramático, você deve estar pensando… Mas eu não resisti e tiver que usar essa frase.
    Até porque README é feito para, como o nome diz, ser lido, e se você tentar contribuir ou usar um projeto Open Source sem ler esse documento, você pode ser, metaforicamente, devorada por dúvidas.

    Hoje escolhi falar sobre READ.ME porque essa é a página inicial de qualquer projeto Open Source, desde um framework famoso como o React.JS, até daquela calculadora que você fez pra praticar seus conhecimentos de programação.

    O que é um README e por que eu deveria me importar?

    Mas o que é o README? 

    O nome, traduzido para o português, fica como LEIAME, o que já dá a dica de que é um documento que deve ser lido. Mas, por quê?

    O README é um arquivo em Markdown (.md) que é considerado o manual de instruções do seu projeto. Ele tem que conter informações úteis para que outras pessoas possam entender, contribuir e usar seu projeto, apenas lendo esse arquivo.

    Você deveria se importar porque esse é o primeiro arquivo que as pessoas vão ler no seu projeto! Ter um bom README também ajuda seu projeto a ter destaque, já que outros projetos muitas vezes não tem um bom README.

    Como criar o arquivo README

    Direto pelo GitHub

    Primeiro vamos às tecnicalidades. 

    Tem várias formas de se criar um README.

    A primeira é quando você criar seu novo projeto no GitHub, na página de criação você vai encontrar o texto “Initialize this repository with:” (Inicialize esse repositório com), e Add um arquivo README é a primeira opção. 

    Você pode clicar na caixinha aqui e seu projeto já vai ser criado com um README:

    Isso vai criar no root do seu repositório o arquivo README.md e o conteúdo desse arquivo é o que aparece na página inicial do repo.

    O README criado aqui é bem básico, mas neste artigo vou ensinar como deixar ele mais completo.

    Criar manualmente

    Se você já tem um projeto criado, ou quer criar o README manualmente, tudo que você tem que fazer é criar um arquivo com o nome README.md no root do projeto, por onde você preferir (terminal, IDE, pelo GitHub mesmo).

    Na imagem abaixo, você pode ver o exemplo de um REAME sendo criado dentro da pasta leiame pelo Terminal:

    Lembre-se de chegar se você está entro da pasta certa antes de criar,

    Criar com o Copilot

    Você também pode, dentro do VSCode, pedir para que o GitHub Copilot crie o README.md para  seu projeto:

    Agora que já temos nosso arquivo criado, vamos editá-lo com os itens necessários?

    Editando seu README

    O arquivo README pode conter diversas informações sobre o seu projeto e muitos desses itens vão ser opcionais, mas um bom README deve ter, no mínimo, o título do projeto e uma boa descrição, como instalar e rodar o projeto, como usar, como contribuir e a licença dele.

    Vamos falar sobre cada um desses itens.

    Título e Descrição

    O título tem que ser algo curto, mas o mais descritivo possível, para ajudar as pessoas a entenderem qual o objetivo principal do projeto.

    Já a descrição complementa o título: O que o projeto faz e para que serve? Quais as tecnologias usadas neste projeto? Você pode adicionar também desafios que você teve criando projetos e features que espera adicionar no futuro.

    Ouso dizer que a descrição é a parte mais importante de qualquer README, então dedique um carinho especial para essa sessão <3

    Como Instalar e Rodar o projeto

    Esse item não se aplica a todos os projetos, mas seu projeto é algo que as pessoas têm que instalar e rodar localmente, isso é algo super importante.

    Aqui você deve incluir um passo-a-passo detalhado de como instalar o projeto e tudo necessário para fazer o ambiente de desenvolvimento rodar sem problemas.

    Como Usar o projeto

    Escreva aqui instruções de como usar seu projeto e adicione exemplos de como ele já foi usado (uma ótima dica é pedir para quem já usa o projeto contribuir nessa sessão).

    Aqui é legal adicionar visuais, como prints do projeto funcionando e qualquer outra coisa que você considere interessante e relevante.

    Como Contribuir

    Projetos Open Source geralmente estão sempre aceitando contribuições (esse é, afinal, o apelo principal de Open Source), então é bom ter um guia de contribuições. Se uma pessoa quiser contribuir, o que ela deve fazer?

    Apenas dar um Fork e criar uma PR ou ela precisa criar uma issue primeiro?

    Temos um guia de diretrizes de contribuição, caso você queira inspiração.

    Licença

    Quando você criar um novo repositório no GitHub, vão te perguntar que licença você quer usar.

    A licença diz às pessoas o que elas podem e o que elas não podem fazer com o seu código, como alterar, usar e distribuir.

    Existem várias e eu geralmente vejo projetos pequenos usando a MIT. Mas se você tem grandes ambições para seu projeto, recomendo pesquisar mais sobre licenças para não ter problemas futuros

    Itens opcionais

    Os itens acima são os que eu considero essenciais para um README bem feito, mas você sempre pode melhorar.

    Como itens opcionais temos:

    • Uma tabela de conteúdo, caso seu README fique muito extenso, é um bom item para facilitar a leitura.
    • Créditos, (caso você teve ajuda ou se inspirou em algum outro projeto ou pessoa, é sempre legal dar crédito a quem merece.
    • Badges são um ótimo visual, e existem todos os tipos de badge. Você só tem que ir no https://shields.io/, copiar o código da badge deseja e adicioná-la ao seu repo. Você pode usar uma badge para demonstrar qual a licença do projeto, por exemplo.

    DESAFIO: Vamos criar um README?

    Isso é tudo que eu tinha para vocês hoje, e quero deixar aqui um desafio: Vá em algum dos projetos que você já tem no GitHub e crie um README bonitinho.

    Depois vem aqui e comenta com o Link do repositório para eu ver!

    Você também pode compartilhar nas redes sociais se preferir, mas por favor mencione esse artigo <3

    Obrigada por ler até aqui,

    Pachi 🥑

     

  • Feature Engineering para Embeddings com SparkML e MLFlow no Databricks Experiments

    Feature Engineering para Embeddings com SparkML e MLFlow no Databricks Experiments

    Hoje resolvi relembrar alguns conceitos de machine learning e entre eles a parte de vetorização de categorias para ter um dataset mais apto para deep learning (Redes neurais). Portanto neste artigo vou demonstrar de forma pura como utilizar a lib do spark de machine learning e criar o experimento ou seja a pipeline no MLFlow dentro do Databricks.

    Escolhendo um dataset adequado:

    Para este artigo vou utilizar um dataset publico do Kaggle chamado parking transaction que é um dataset em csv que contém registros de transações de estacionamento de várias fontes, incluindo medidores de estacionamento e aplicativos de pagamento móveis.

    -> https://www.kaggle.com/datasets/aniket0712/parking-transactions

    Agora vamos montar o notebook e realizar uma série de passos para fazer feature engineering, especificamente para criar embeddings **categóricos usando Apache Spark e técnicas de **NLP (Natural Language Processing). Vou detalhar cada célula e seu objetivo principal.

    📌Requisitos:

    • Databricks (recomendado) ou um ambiente com Apache Spark configurado (Spark 3.0 ou superior recomendado).
    • Suporte para PySpark (Python API para Spark) pyspark (Spark ML)
    • kagglehub (para baixar datasets do Kaggle)
    • mlflow (para registro de modelos no MLflow)

    Caso esteja utilizando o Databricks, você só precisa instalar a lib do kagglehub.

    📌. Kaggle Authentication (opcional):

    Caso execute localmente ou fora do Databricks, precisará configurar o acesso ao Kaggle:

    ~/.kaggle/kaggle.json
    
    • Dê as permissões adequadas:

    chmod 600 ~/.kaggle/kaggle.json
    Nota: No Databricks, pode ser mais fácil baixar manualmente o dataset ou usar uma integração alternativa (como upload direto).

    Image description

    Copiar dados para o DBFS (Databricks File System):

    O arquivo baixado localmente é copiado para o DBFS, ambiente Databricks que permite processamento distribuído no Spark.

    Image description

    Carregar o dataset no Spark DataFrame:

    Os dados são carregados em um DataFrame Spark para processamento distribuído.

    Image description

    Image description

    Seleção e tratamento inicial de colunas:

    Apenas colunas relevantes são selecionadas: “Source”, “Duration in Minutes”, “App Zone Group”, “Payment Method”, “Location Group”, “Amount”.

    Valores null são tratados explicitamente, substituindo por valores apropriados para evitar problemas nas etapas seguintes.

    Image description

    Identificação de variáveis categóricas:

    As colunas categóricas (“Source”, “App Zone Group”, “Payment Method”, “Location Group”) são avaliadas para verificar o número de categorias únicas que cada uma contém, ajudando a decidir quais serão usadas no embedding.

    Image description

    Ajuste de tipos e nomes das colunas:

    As colunas numéricas são convertidas para tipo double.
    O nome das colunas é normalizado para o formato snake_case (ex.: “Duration in Minutes” para “duration_in_minutes”).

    Image description

    Função para gerar embeddings com Word2Vec:

    Essa é a principal célula do notebook. Aqui ocorre a criação de embeddings categóricos.

    O processo envolve:

    • Combinação de categorias: Todas as colunas categóricas são concatenadas em uma única coluna de texto.
    • Tokenização: Essa coluna combinada é dividida em tokens individuais (palavras).
    • Treinamento Word2Vec: Um modelo Word2Vec é treinado nos tokens categóricos. Este modelo captura a semântica das categorias ao gerar representações numéricas (vetores).
    • Pipeline Spark ML: Essas etapas são encapsuladas em um pipeline Spark, que facilita a execução sequencial e reutilização do processo.

    Image description

    Image description

    Motivos do uso do Word2Vec:

    Representação numérica semântica: Captura similaridades entre categorias, ajudando modelos posteriores a entender relações implícitas.

    Eficácia em modelos ML: Os embeddings produzidos são úteis em modelos de aprendizado profundo, banco de dados vetoriais e ou outros modelos Spark ML que precisam de inputs numéricos contínuos.

    Transformar variáveis categóricas em representações vetoriais (embeddings) com o modelo Word2Vec, além de registrar o pipeline resultante no MLflow para garantir rastreabilidade e versionamento.

    1. Seleção de Categorias para Embeddings
      Primeiramente, definimos as variáveis categóricas que serão convertidas em embeddings.
    2. Amostragem dos Dados
      Em seguida, selecionamos uma amostra menor dos dados originais para fins de demonstração, economizando tempo computacional.
    3. Construção da Pipeline de Embeddings
      Construímos então uma pipeline personalizada com Spark ML, que executa os seguintes passos automaticamente:
    • Tratamento de valores nulos (substituindo por “desconhecido”).
    • Combinação das categorias em uma única string (coluna intermediária todas_categorias).
    • Tokenização dessa string em tokens individuais (coluna categorias_tokenizadas).
    • Geração de embeddings via modelo Word2Vec (vetores armazenados na coluna categorias_embeddings).

    Image description

    Registro da Pipeline no MLflow

    A pipeline treinada é registrada no MLflow, uma plataforma aberta para gerenciar o ciclo de vida de modelos de Machine Learning, permitindo versionamento, reproducibilidade e compartilhamento:

    Image description

    Conclusão e motivo para eu relembrar e escrever este artigo:

    Quando falamos de embeddings para serem armazenados em um Vector Database com o objetivo posterior de aplicar técnicas como Retrieval-Augmented Generation (RAG), existem essencialmente duas abordagens populares:

    1. API de Embeddings (Ex.: OpenAI, Cohere, Hugging Face)
    2. Treinamento local de embeddings (Ex.: Spark Word2Vec)

    Ambas têm vantagens e desvantagens importantes que podem definir claramente a melhor escolha para seu caso específico.

    API de Embeddings (OpenAI, Cohere, Hugging Face)
    Exemplos populares:

    • OpenAI Embeddings API (text-embedding-ada-002).
    • Cohere Embeddings.
    • Hugging Face API (Sentence-BERT).

    Pontos Fortes ✅:

    • Alta qualidade dos embeddings: já treinados em datasets massivos.
    • Sem necessidade de infraestrutura própria: rápida integração, sem overhead técnico.
    • Bom para RAG: Embeddings semânticos profundos otimizados para buscas contextuais.

    Pontos Fracos ❌:

    • Custo variável: Pode se tornar caro com grandes volumes.
    • Latência da API: Depende da disponibilidade externa (tempo de resposta).
    • Privacidade e compliance: Seus dados saem da sua infraestrutura.

    Por que os Embeddings são essenciais para um Vector Database e RAG?

    Em um fluxo de Retrieval-Augmented Generation (RAG):

    Geração dos embeddings:
    O texto/documento é convertido em vetores (embeddings).

    Armazenamento em vector database (Qdrant, Pinecone, Chroma):
    Armazena esses vetores para buscas rápidas baseadas em similaridade.

    Retrieval eficiente:
    Ao receber um prompt, converte-se em embeddings e realiza busca por similaridade no Vector Database, retornando o contexto mais relevante para o modelo generativo

    Portanto espero que tenham gostado, deixo abaixo meu Linkedin e Repositório do projeto: