<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maria Paula</title>
    <description>The latest articles on DEV Community by Maria Paula (@mariapaulalsf).</description>
    <link>https://dev.to/mariapaulalsf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4225242%2Fc7916c84-8ec0-4a9a-aa0d-7360902cb952.jpg</url>
      <title>DEV Community: Maria Paula</title>
      <link>https://dev.to/mariapaulalsf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariapaulalsf"/>
    <language>en</language>
    <item>
      <title>Spec-Driven Development na prática: testando o fluxo em um projeto de ML</title>
      <dc:creator>Maria Paula</dc:creator>
      <pubDate>Wed, 04 Nov 2026 02:32:27 +0000</pubDate>
      <link>https://dev.to/mariapaulalsf/spec-driven-development-na-pratica-testando-o-fluxo-em-um-projeto-de-ml-31if</link>
      <guid>https://dev.to/mariapaulalsf/spec-driven-development-na-pratica-testando-o-fluxo-em-um-projeto-de-ml-31if</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Pedir código a uma IA com um prompt curto deixa muita coisa em aberto. O modelo precisa presumir o que ninguém escreveu, e o erro costuma aparecer só no fim, quando o código já está pronto. O Spec-Driven Development (SDD) tenta resolver isso escrevendo uma especificação antes do código.&lt;/p&gt;

&lt;p&gt;Um exemplo de problema que só aparece depois está no meu projeto, o &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics" rel="noopener noreferrer"&gt;Brasileirão Pro Analytics&lt;/a&gt;. A primeira versão calculava as estatísticas dos times (posse, desarmes, gols) como acumulados da temporada inteira e usava esses valores para prever jogos da própria temporada. Na prática, o modelo "via" resultados que ainda não tinham acontecido, um caso de &lt;em&gt;data leakage&lt;/em&gt;. Corrigi isso no commit &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/commit/b96e6ba" rel="noopener noreferrer"&gt;&lt;code&gt;b96e6ba&lt;/code&gt;&lt;/a&gt;, passando a calcular as &lt;em&gt;features&lt;/em&gt; só com jogos anteriores a cada partida.&lt;/p&gt;

&lt;p&gt;Neste artigo eu aplico o SDD em uma tarefa seguinte do mesmo projeto: transformar a temporada em parâmetro, para o código não depender de 2025 e 2026 escritos à mão. Depois comparo o resultado com o que a própria spec exigia. Os arquivos estão na branch &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/tree/experimento-sdd" rel="noopener noreferrer"&gt;&lt;code&gt;experimento-sdd&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Spec-Driven Development
&lt;/h2&gt;

&lt;p&gt;SDD é escrever uma especificação antes de codar com IA e usar essa especificação como referência para a pessoa e para o agente. A Birgitta Böckeler, no site do Martin Fowler, separa três níveis de uso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;spec-first:&lt;/strong&gt; a spec é escrita antes e usada no fluxo de desenvolvimento com IA;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spec-anchored:&lt;/strong&gt; a spec é mantida depois que a tarefa termina, para evoluir e manter a funcionalidade;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;spec-as-source:&lt;/strong&gt; a spec é o arquivo-fonte principal e a pessoa não mexe no código.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ela também diferencia spec de &lt;em&gt;memory bank&lt;/em&gt;. A spec descreve o comportamento de uma funcionalidade e vale para as tarefas que criam ou alteram essa funcionalidade. O memory bank reúne regras e descrições gerais do produto e da base de código, válidas para todas as sessões. No spec-kit, esse papel é da &lt;em&gt;constitution&lt;/em&gt;, que guarda princípios de alto nível aplicados a toda mudança.&lt;/p&gt;

&lt;p&gt;O texto do GitHub Blog (Den Delimarsky, 2 set. 2025) descreve o Spec Kit em quatro fases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;specify:&lt;/strong&gt; usuários, problema e critérios de sucesso, sem detalhe técnico;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plan:&lt;/strong&gt; stack, arquitetura e restrições;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tasks:&lt;/strong&gt; pedaços pequenos que dá para implementar e testar isoladamente;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;implement:&lt;/strong&gt; o agente executa as tarefas e a pessoa revisa.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Na análise da Böckeler, o fluxo do spec-kit começa pela constitution, seguida de specify, plan e tasks.&lt;/p&gt;

&lt;p&gt;A Thoughtworks colocou a técnica no anel &lt;em&gt;Assess&lt;/em&gt; do Technology Radar de novembro de 2025, que significa que vale explorar para entender como ela afetará a organização. O Radar diz que os fluxos continuam elaborados e opinativos, que as ferramentas se comportam de forma bem diferente conforme o tamanho e o tipo da tarefa e que algumas geram arquivos de especificação longos e difíceis de revisar. A página do Radar indica que o item não está na edição atual, então a classificação vale para aquela edição.&lt;/p&gt;

&lt;h2&gt;
  
  
  O experimento
&lt;/h2&gt;

&lt;p&gt;O Brasileirão Pro Analytics prevê o resultado de jogos do Campeonato Brasileiro. Ele lê os jogos de arquivos CSV, calcula as &lt;em&gt;features&lt;/em&gt; usando só jogos anteriores a cada partida, treina uma regressão de Poisson com a temporada 2025 e testa com os jogos já realizados de 2026.&lt;/p&gt;

&lt;p&gt;O ponto de partida foi o commit &lt;code&gt;b9e399f&lt;/code&gt;. Nele, os anos 2025 e 2026 estavam escritos em &lt;code&gt;src/features.py&lt;/code&gt; (valor padrão do argumento &lt;code&gt;temporadas&lt;/code&gt;), em &lt;code&gt;src/app.py&lt;/code&gt; e em &lt;code&gt;src/avaliar_modelo.py&lt;/code&gt;. Os nomes dos arquivos já eram montados a partir do ano (&lt;code&gt;partidas_{ano}.csv&lt;/code&gt;): o que estava fixo era o ano.&lt;/p&gt;

&lt;p&gt;A tarefa foi esta: a temporada de treino e a de teste passam a ser parâmetros. Escolhi porque é pequena e tem critério de aceitação fácil de conferir.&lt;/p&gt;

&lt;p&gt;Segui as fases do Spec Kit (constitution, specify, plan, tasks e implement). Os documentos ficaram em &lt;code&gt;.spec/&lt;/code&gt;, uma pasta do próprio projeto, que não é a &lt;code&gt;.specify/&lt;/code&gt; usada pela CLI do Spec Kit. Em termos da Böckeler, foi um uso spec-first: as specs foram escritas antes da mudança e não foram atualizadas depois (as tarefas continuam sem marcação).&lt;/p&gt;

&lt;h2&gt;
  
  
  Passo a passo e artefatos
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Constitution&lt;/strong&gt; (&lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/blob/experimento-sdd/.spec/constitution.md" rel="noopener noreferrer"&gt;&lt;code&gt;.spec/constitution.md&lt;/code&gt;&lt;/a&gt;). Quatro regras: código compatível com Python 3.10+; zero &lt;em&gt;data leakage&lt;/em&gt;, com &lt;em&gt;features&lt;/em&gt; só a partir de eventos anteriores à rodada prevista; testes automatizados em &lt;code&gt;/tests&lt;/code&gt; para novos métodos, lógicas de &lt;em&gt;features&lt;/em&gt; ou mudanças de arquitetura; e &lt;code&gt;README.md&lt;/code&gt; refletindo o estado atual e as limitações do modelo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specify&lt;/strong&gt; (&lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/blob/experimento-sdd/.spec/specify.md" rel="noopener noreferrer"&gt;&lt;code&gt;.spec/specify.md&lt;/code&gt;&lt;/a&gt;). Descreve o problema (anos fixos no código impedem usar 2027 sem editar vários lugares), o objetivo (receber ano de treino e de teste como parâmetros) e quatro critérios de aceite:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;os testes de &lt;code&gt;tests/test_features.py&lt;/code&gt; continuam passando;&lt;/li&gt;
&lt;li&gt;a avaliação com 2025 e 2026 repete 48,0% de acurácia e 1,020 de &lt;em&gt;log loss&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;o painel Streamlit renderiza como antes;&lt;/li&gt;
&lt;li&gt;nenhum ano sobra solto na lógica de carregamento de dados.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt; (&lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/blob/experimento-sdd/.spec/plan.md" rel="noopener noreferrer"&gt;&lt;code&gt;.spec/plan.md&lt;/code&gt;&lt;/a&gt;). Três mudanças: &lt;code&gt;features.py&lt;/code&gt; passa a receber &lt;code&gt;ano_treino&lt;/code&gt; e &lt;code&gt;ano_teste&lt;/code&gt;; &lt;code&gt;app.py&lt;/code&gt; ganha as constantes &lt;code&gt;ANO_TREINO&lt;/code&gt; e &lt;code&gt;ANO_TESTE&lt;/code&gt;; &lt;code&gt;avaliar_modelo.py&lt;/code&gt; lê os anos de &lt;code&gt;sys.argv&lt;/code&gt;, com 2025 e 2026 como padrão.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks&lt;/strong&gt; (&lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/blob/experimento-sdd/.spec/tasks.md" rel="noopener noreferrer"&gt;&lt;code&gt;.spec/tasks.md&lt;/code&gt;&lt;/a&gt;). Três tarefas, uma para cada arquivo do plano.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implement&lt;/strong&gt; (commit &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/commit/b21411b" rel="noopener noreferrer"&gt;&lt;code&gt;b21411b&lt;/code&gt;&lt;/a&gt;, 28/10/2026, 21:51). A mudança alterou &lt;code&gt;src/app.py&lt;/code&gt; (8 linhas adicionadas, 4 removidas) e &lt;code&gt;src/avaliar_modelo.py&lt;/code&gt; (15 adicionadas, 13 removidas). O &lt;code&gt;features.py&lt;/code&gt; não mudou: o plano supunha chamadas de leitura com caminho fixo nesse arquivo, mas &lt;code&gt;carregar_partidas&lt;/code&gt; já recebia &lt;code&gt;temporadas&lt;/code&gt; e montava os nomes com o ano. Existe um único commit da implementação, então não há registro de erros ou correções no meio do caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verificação dos resultados
&lt;/h2&gt;

&lt;p&gt;Comparei o commit com os critérios da spec e com as regras da constitution.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Resultado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Testes continuam passando&lt;/td&gt;
&lt;td&gt;Sim: os 3 testes de &lt;code&gt;tests/test_features.py&lt;/code&gt; passam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mesmos resultados com 2025 e 2026&lt;/td&gt;
&lt;td&gt;Sim: &lt;code&gt;python src/avaliar_modelo.py&lt;/code&gt;, com e sem os argumentos &lt;code&gt;2025 2026&lt;/code&gt;, repete 48,0% de acurácia e 1,0201 de &lt;em&gt;log loss&lt;/em&gt;, com saída idêntica à de antes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Painel Streamlit renderiza como antes&lt;/td&gt;
&lt;td&gt;Sim, aberto no navegador com &lt;code&gt;streamlit run src/app.py&lt;/code&gt; (conferência manual, sem registro em &lt;code&gt;experimento/&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nenhum ano solto na lógica de carregamento&lt;/td&gt;
&lt;td&gt;Parcial: &lt;code&gt;features.py&lt;/code&gt; mantém &lt;code&gt;temporadas=(2025, 2026)&lt;/code&gt; como padrão; &lt;code&gt;app.py&lt;/code&gt; e &lt;code&gt;avaliar_modelo.py&lt;/code&gt; mantêm 2025 e 2026 como padrão, como o plano previa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Constitution, regra 3: testes para o que é novo&lt;/td&gt;
&lt;td&gt;Não: nenhum teste foi adicionado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Constitution, regra 4: README atualizado&lt;/td&gt;
&lt;td&gt;Não: o README não menciona os argumentos de &lt;code&gt;avaliar_modelo.py&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O arquivo &lt;code&gt;experimento/depois_previsoes.txt&lt;/code&gt; é idêntico ao &lt;code&gt;antes_previsoes.txt&lt;/code&gt;, mas esse teste não passa por &lt;code&gt;app.py&lt;/code&gt; nem por &lt;code&gt;avaliar_modelo.py&lt;/code&gt;, que são os arquivos alterados. O que valida a mudança é a comparação das métricas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outras temporadas (2027)
&lt;/h2&gt;

&lt;p&gt;Não existe &lt;code&gt;partidas_2027.csv&lt;/code&gt; no repositório, e ainda não há resultados de 2027. Em testes com arquivos criados só para esta verificação (nenhum está no repositório), o comportamento foi este:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;arquivo vazio:&lt;/strong&gt; o &lt;code&gt;avaliar_modelo.py&lt;/code&gt; termina com &lt;code&gt;EmptyDataError&lt;/code&gt; e o app mostra a mensagem de erro de leitura;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;arquivo só com cabeçalho:&lt;/strong&gt; os dois terminam com &lt;code&gt;ValueError&lt;/code&gt; do &lt;code&gt;StandardScaler&lt;/code&gt;, por falta de amostras;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;calendário com jogos sem placar:&lt;/strong&gt; o app abre e mostra as previsões, mas exibe 0,0% de acurácia, que na verdade significa "sem jogos para avaliar"; o &lt;code&gt;avaliar_modelo.py&lt;/code&gt; falha pelo mesmo &lt;code&gt;ValueError&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O parâmetro funciona para anos que têm dados. O código ainda não trata uma temporada sem jogos realizados, e carregar um arquivo não valida o modelo: sem resultados não há acurácia nem &lt;em&gt;log loss&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tempo
&lt;/h2&gt;

&lt;p&gt;O arquivo &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/blob/experimento-sdd/experimento/tempo.txt" rel="noopener noreferrer"&gt;&lt;code&gt;experimento/tempo.txt&lt;/code&gt;&lt;/a&gt; registra o início às 21:32, e o commit da implementação saiu às 21:51. Foram cerca de 20 minutos no total, com documentos, mudança no código e verificação. Não separei o tempo de cada etapa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefícios e limitações
&lt;/h2&gt;

&lt;p&gt;Os autores que li apontam estes benefícios. No texto do GitHub Blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Menos adivinhação.&lt;/strong&gt; Com um prompt vago o modelo presume muitos requisitos, e a spec reduz isso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O quê separado do como.&lt;/strong&gt; A spec fixa a intenção, e o plano pode mudar sem reescrever tudo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tarefas testáveis.&lt;/strong&gt; Cada tarefa pequena pode ser implementada e testada isoladamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E estas limitações. Na análise da Böckeler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tamanho do processo.&lt;/strong&gt; O Kiro transformou um bug pequeno em 4 user stories e 16 critérios de aceitação. O spec-kit pareceu exagerado para uma funcionalidade de tamanho médio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controle.&lt;/strong&gt; O agente ignorou instruções e, em um caso, recriou classes que já existiam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rigidez.&lt;/strong&gt; Ela compara o spec-as-source com o MDD e teme herdar as desvantagens do MDD e dos LLMs, ou seja, a rigidez de um e a imprevisibilidade do outro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O Radar da Thoughtworks acrescenta que podemos estar reaprendendo uma "lição amarga": escrever à mão regras detalhadas para a IA não escala.&lt;/p&gt;

&lt;p&gt;No meu experimento, os critérios de aceite da spec funcionaram como lista de conferência. Compará-los com o commit mostrou lacunas que eu não tinha percebido: o padrão &lt;code&gt;(2025, 2026)&lt;/code&gt; que continua em &lt;code&gt;features.py&lt;/code&gt;, a falta de teste novo e de atualização do README, que eram regras da minha própria constitution, e o resultado do painel sem registro. Também mostrou que o plano descrevia o &lt;code&gt;features.py&lt;/code&gt; de um jeito diferente do que ele era. A spec ajudou a achar esses problemas, mas depois da implementação, e não os evitou.&lt;/p&gt;

&lt;p&gt;Sobre o tamanho do processo, foram quatro documentos curtos (40 linhas ao todo) para uma mudança em dois arquivos. É a proporção que a Böckeler questiona. Não comparei com um prompt direto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Para uma funcionalidade pequena, como a parametrização de temporadas, o SDD me pareceu excessivo: quatro documentos para alterar dois arquivos. Essa é minha impressão, e ela se apoia em evidências limitadas. O tempo total foi de cerca de 20 minutos, sem divisão por etapa, e não repeti a tarefa com um prompt direto, então não posso dizer que o SDD foi mais lento ou menos eficiente do que essa alternativa.&lt;/p&gt;

&lt;p&gt;O que a spec deu de concreto foi uma lista de critérios para conferir o resultado, e foi essa conferência que mostrou o que faltava. Minha hipótese é que o SDD compensa mais em mudanças com vários pontos de falha e critérios de aceitação mais amplos, como uma pipeline de &lt;em&gt;web scraping&lt;/em&gt; ou a migração do banco de dados, e menos em refatorações pequenas, &lt;em&gt;hotfixes&lt;/em&gt; ou na adição de um único parâmetro. Não testei esses cenários.&lt;/p&gt;

&lt;p&gt;Este é um caso isolado (uma funcionalidade, um projeto) e não serve de regra geral. Os documentos, o código e os registros do experimento estão na &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics/tree/experimento-sdd" rel="noopener noreferrer"&gt;branch &lt;code&gt;experimento-sdd&lt;/code&gt;&lt;/a&gt;, para quem quiser conferir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;BÖCKELER, Birgitta. &lt;a href="https://www.martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html" rel="noopener noreferrer"&gt;Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl&lt;/a&gt;. martinfowler.com, 15 out. 2025.&lt;/li&gt;
&lt;li&gt;DELIMARSKY, Den. &lt;a href="https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit" rel="noopener noreferrer"&gt;Spec-driven development with AI: Get started with a new open source toolkit&lt;/a&gt;. GitHub Blog, 2 set. 2025.&lt;/li&gt;
&lt;li&gt;THOUGHTWORKS. &lt;a href="https://www.thoughtworks.com/radar/techniques/spec-driven-development" rel="noopener noreferrer"&gt;Spec-driven development&lt;/a&gt;. Technology Radar, edição de nov. 2025.&lt;/li&gt;
&lt;li&gt;GITHUB. &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;Spec Kit&lt;/a&gt;. Repositório da ferramenta. Acesso em: 28 out. 2026.&lt;/li&gt;
&lt;li&gt;Projeto: &lt;a href="https://github.com/mariapaulalsf/brasileirao-pro-analytics" rel="noopener noreferrer"&gt;Brasileirão Pro Analytics&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>machinelearning</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
