Skip to content

Instantly share code, notes, and snippets.

@vedovelli
Last active May 26, 2025 08:54
Show Gist options
  • Save vedovelli/36fe8488a1fd397a521b2977d0de1d48 to your computer and use it in GitHub Desktop.
Save vedovelli/36fe8488a1fd397a521b2977d0de1d48 to your computer and use it in GitHub Desktop.

Plano de Refatoração para o Código do AI Task Manager

Este documento descreve um plano abrangente para refatorar a aplicação AI Task Manager, seguindo as melhores práticas de engenharia de software. O plano aborda separação de responsabilidades, organização de código e manutenibilidade.

Instruções gerais

  • Módulos de servidor (.server.ts) jamais devem ser referenciados em arquivos de componentes React, a não ser que este arquivo seja um módulo de rota (vivendo em ~/app/routes)

1. Implementação da Camada de Serviço

Objetivo: Mover a lógica de negócios para camadas de serviço para separar responsabilidades e melhorar a testabilidade.

Estratégia de implementação:

  1. Criar módulos de serviço robustos:

    • task.server.ts: Implementar operações CRUD com tratamento de erros adequado
    • chat.server.ts: Implementar operações de gerenciamento de chat e processamento de mensagens
    • Usar classes de erro personalizadas para erros específicos do domínio
  2. Estabelecer padrões consistentes para funções de serviço:

    • Funções de serviço com parâmetros diretos (ex: updateTask(id, data))
    • Funções manipuladoras para processar FormData (ex: handleTaskCreateOrUpdate(formData))
    • Funções auxiliares para formatar e preparar dados (ex: prepareMessagesForDisplay(messages))
  3. Refatorar rotas específicas:

    • task-new.tsx: Usar funções de serviço para criação/atualização de tarefas
    • task-edit.tsx: Substituir chamadas diretas ao Prisma por funções de serviço
    • task-view.tsx: Delegar a busca de dados à camada de serviço
    • tasks.tsx: Usar funções de serviço para listagem e exclusão
    • chats.tsx: Usar funções de serviço para operações de chat
    • api.chat.ts: Usar a camada de serviço para processamento de mensagens

Impacto esperado:

  • Maior testabilidade da lógica de negócios
  • Separação clara entre manipuladores de rota e operações de negócio
  • Tratamento de erros centralizado
  • Manutenção e extensões futuras facilitadas

2. Reorganização de Pastas por Funcionalidade

Objetivo: Organizar componentes por domínio de funcionalidade para melhorar a descoberta de código.

Estratégia de implementação:

  1. Criar diretórios específicos por funcionalidade:

    • Criar diretório app/features/chats
    • Mover componentes relacionados a chat da pasta tasks para a pasta chats
    • Atualizar imports em todo o código
  2. Organizar componentes específicos de tarefas:

    • Manter toda a lógica e UI de tarefas em app/features/tasks
    • Garantir que cada componente trate de um único aspecto da funcionalidade
    • Verificar consistência na nomenclatura
  3. Extrair componentes de UI reutilizáveis:

    • Criar componente TaskDetails em app/features/tasks
    • Simplificar task-view.tsx para focar no carregamento de dados
  4. Revisar componentes compartilhados:

    • Manter componentes como NavMain, NavUser, AppSidebar, SiteHeader em app/components
    • Refatorar ChatInterface para aceitar props ao invés de usar useLoaderData diretamente

Impacto esperado:

  • Organização mais clara do código por domínio
  • Melhor separação de responsabilidades
  • Maior reutilização de componentes
  • Manutenção facilitada com o crescimento da aplicação

3. Eliminação de Lógica Duplicada (DRY)

Objetivo: Remover duplicação de código e centralizar operações comuns.

Estratégia de implementação:

  1. Criar camada de serviço para operações consistentes:

    • Implementar funções de serviço reutilizáveis entre rotas
    • Estabelecer padrões consistentes de tratamento de erros
    • Adicionar segurança de tipo com classes de erro personalizadas
  2. Criar manipuladores para processamento de formulários:

    • handleTaskCreateOrUpdate(formData) em task.server.ts
    • handleTaskDelete(formData) em task.server.ts
    • handleChatUpdate(formData) em chat.server.ts
    • handleChatDelete(formData) em chat.server.ts
    • handleChatDataForTaskCreation(url) em chat.server.ts
  3. Unificar parsing/formatação de campos de tarefas:

    • Criar funções utilitárias para operações comuns:
// Utilitário para converter string multilinha em array JSON
export function linesToJsonArray(str: string): string {
  return JSON.stringify(
    str
      .split("\n")
      .map((s) => s.trim())
      .filter(Boolean)
  );
}

// Utilitário para interpretar arrays JSON com segurança
export function parseJsonList(jsonStr?: string): string[] {
  try {
    return jsonStr ? JSON.parse(jsonStr) : [];
  } catch {
    return [];
  }
}
  1. Padronizar padrões de UI:
    • Extrair padrões comuns de tabelas e formulários
    • Criar botões reutilizáveis para ações como deletar/editar
    • Usar exibição de mensagens de erro consistente

Impacto esperado:

  • Redução de duplicação de código
  • Comportamento mais consistente na aplicação
  • Manutenção e correção de bugs facilitadas
  • Melhor experiência para desenvolvedores

4. Garantir Responsabilidade Única de Módulos

Objetivo: Cada módulo deve ter uma única responsabilidade e razão para mudar.

Estratégia de implementação:

  1. Implementar camada de serviço com responsabilidades claras:

    • task.server.ts para lógica de tarefas
    • chat.server.ts para chats e mensagens
    • Cada função com um propósito claro e focado
  2. Manter arquivos de rota enxutos:

    • Focar exclusivamente no tratamento de requisição/resposta
    • Delegar lógica de negócio para funções de serviço
    • Retornar dados apropriados para a interface
    • Nenhuma operação direta no banco de dados
  3. Refatorar componentes de UI complexos:

    • Dividir componentes como ChatsList se estiverem sobrecarregados
    • Usar composição para interações complexas
  4. Centralizar integração com IA:

    • Manter toda lógica relacionada ao OpenAI em chat.server.ts
    • Documentar claramente interações com IA

Impacto esperado:

  • Código mais fácil de entender e manter
  • Separação de responsabilidades mais clara
  • Testes unitários mais focados
  • Menor complexidade nos módulos

5. Nomenclatura e Consistência

Objetivo: Estabelecer convenções consistentes de nomes e padrões de código.

Estratégia de implementação:

  1. Definir padrões consistentes de parâmetros:

    • Parâmetros diretos para funções principais de serviço
    • Objetos FormData para manipuladores
    • Tratamento de erros com classes personalizadas
    • Objetos de resposta padronizados (ex: { success: boolean, error?: string })
  2. Padronizar nomenclatura de arquivos:

    • Usar task-form.tsx, tasks-list.tsx, etc. dentro da pasta de tarefas
    • Usar plural para listas, singular para visualizações individuais
    • Nomes de arquivos em kebab-case, funções de componente em PascalCase
  3. Manter consistência nos imports:

    • Atualizar todos os imports ao mover arquivos
    • Usar padrões consistentes de importação
    • Agrupar imports por tipo (React, bibliotecas, componentes locais)

Impacto esperado:

  • Base de código mais previsível
  • Navegação facilitada
  • Melhor experiência de desenvolvimento
  • Menos erros por padrões inconsistentes

6. Melhorias Adicionais

Objetivo: Aprimorar e elevar a qualidade do código além das mudanças estruturais.

Estratégia de implementação:

  1. Implementar tratamento de erros abrangente:

    • Criar classes de erro personalizadas (ex: TaskNotFoundError, ChatUpdateError)
    • Estabelecer formato consistente de resposta a erros
    • Adicionar verificação de tipo adequada para erros desconhecidos
  2. Adicionar documentação:

    • Comentários JSDoc em todas as funções de serviço
    • Documentar requisitos de parâmetros e valores de retorno
    • Documentar possíveis erros e casos extremos
    • Comentários inline para lógica complexa
  3. Considerar melhorias futuras:

    • Abstração de repositório para operações no banco de dados
    • Maior separação entre lógica de negócio e acesso a dados
    • Padronização de formatos de resposta dos serviços
    • Implementação consistente de exibição de erros na UI
  4. Testar cuidadosamente:

    • Verificar todos os fluxos após refatoração
    • Testar casos de tratamento de erro
    • Garantir preservação do comportamento existente

Estratégia de Implementação

Para implementar este plano de refatoração, seguiremos estas etapas:

  1. Criar módulos de serviço primeiro:

    • Começar com operações CRUD essenciais
    • Implementar tratamento de erros
    • Adicionar operações especializadas
    • Adicionar manipuladores para processamento de formulários
  2. Refatorar rotas uma a uma:

    • Começar com rotas mais simples como tasks.tsx e task-view.tsx
    • Avançar para rotas mais complexas como task-new.tsx e api.chat.ts
    • Testar cada rota cuidadosamente após refatorar
  3. Reorganizar estrutura de pastas:

    • Criar novas pastas por funcionalidade
    • Mover componentes e atualizar imports
    • Testar para garantir funcionamento
  4. Eliminar duplicação:

    • Criar funções utilitárias
    • Atualizar código para usar os utilitários
    • Testar cuidadosamente
  5. Melhorar documentação e polimento:

    • Adicionar comentários JSDoc
    • Garantir nomenclatura e padrões consistentes
    • Corrigir inconsistências remanescentes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment