vue-componentes/.agent/workflows/otimizar-codigos.global.md

6.7 KiB
Raw Blame History

description
Otimizar código e documentar padrões de qualidade (estrutura, limites, JSDoc e tipagem)

Workflow: Qualidade e Documentação de Código

🎯 Objetivo

Unificar as regras de estrutura de arquivos, otimização e documentação em um único fluxo de referência para o projeto eli-vue.


1️⃣ Limite de Linhas por Arquivo

Nenhum arquivo *.vue, *.ts ou *.tsx pode ultrapassar 250 linhas.

Essa regra existe para facilitar a leitura humana, a revisão de código e a manutenção a longo prazo.

O script scripts/check-vue-linhas.sh valida automaticamente os arquivos .vue no prebuild.

Estratégias quando o limite se aproxima:

Situação Ação
Template longo Extrair seções como subcomponentes
CSS extenso Mover para <nome>.css co-localizado
setup() extenso Extrair subcomponentes, CSS ou Dispatch Table
Modal/Dialog embutido Sempre em componente separado (*Modal.vue)
Handlers e dispatch Extrair para handlers.ts ou dispatch.ts

2️⃣ Estrutura de Componentes Vue

defineComponent obrigatório

Todo componente Vue deve usar defineComponent para garantir inferência de tipos correta e consistência.

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'MeuComponente',
  setup() {
    // lógica aqui
  }
})
</script>

Por que é importante:

  • Inferência de tipos TypeScript correta dentro do componente
  • Reconhecimento por ferramentas de análise estática e IDEs
  • Compatível com Options API e Composition API com setup()
  • Padronização entre todos os componentes do projeto

setup() não pode ser externo

O setup() deve estar sempre dentro do componente .vue. Não é permitido extrair ou delegar o setup para nenhum arquivo externo.

// ❌ Proibido — setup delegado inteiramente para arquivo externo
// useEliTabela.ts
export function useEliTabela(props, emit) { ... }

// EliTabela.vue
export default defineComponent({
  setup(props, { emit }) {
    return useEliTabela(props, emit)  // setup é apenas um proxy vazio
  }
})
// ✅ Correto — setup com lógica própria dentro do componente
// EliTabela.vue
export default defineComponent({
  setup(props, { emit }) {
    const estado = ref(null)
    const carregar = async () => { ... }
    return { estado, carregar }
  }
})

Composables use*.ts podem encapsular lógica reutilizável pontual (ex: useFormatador, usePermissao), mas nunca substituir ou esvaziar o setup() do componente. Se o componente ultrapassar 250 linhas, a solução é extrair subcomponentes, mover CSS ou usar Dispatch Table — não esvaziar o setup.


Desassociação de CSS

A separação de estilos em arquivo externo é permitida e recomendada quando o CSS contribui significativamente para o total de linhas.

Padrão de nomenclatura:

MeuComponente.vue
MeuComponente.css

O .vue importa o arquivo CSS no script:

import './MeuComponente.css'

Ou via tag <style>:

<style src="./MeuComponente.css" />

Dispatch Table em Arquivo Separado

O uso de Dispatch Table (mapa de funções) em arquivos separados é bem-vindo para eliminar blocos longos de if/else ou switch.

// handlers.ts
export const acaoHandlers: Record<string, () => void> = {
  salvar: () => { ... },
  cancelar: () => { ... },
  excluir: () => { ... },
}
// MeuComponente.vue
import { acaoHandlers } from './handlers'

function executar(acao: string) {
  acaoHandlers[acao]?.()
}

3️⃣ Documentação em Código (JSDoc)

Princípios básicos

  • Por que, não o Quê: Documente o raciocínio por trás da decisão arquitetural, não o mecanismo óbvio que o TypeScript já expressa.
  • Nomenclatura limpa: Confie na auto-documentação de nomes expressivos antes de escrever comentários de texto livre.

Funções compartilhadas — JSDoc obrigatório

Toda função central ou de uso compartilhado (frontend, backend, mobile ou bibliotecas comuns) deve ter cabeçalho em JSDoc.

/**
 * Busca os detalhes de uma entidade baseando-se no ID fornecido e calcula privilégios aplicáveis.
 * Não utilizar em fluxos de processamento em lote para evitar sobrecarga de requisições.
 *
 * @param tenantId  - Identificador único do cliente/tenant no sistema
 * @param entityId  - ID exclusivo identificando o registro na base de dados
 * @returns Retorna o objeto consolidado com dados ou `null` caso não seja encontrado
 */
export const obterDetalhesEntidade = async (tenantId: string, entityId: string) => { ... }

4️⃣ Casts Temporários e Exceções de Tipagem

Devido à política TypeScript sem any, coerções agressivas requerem justificativa obrigatória em comentário.

// Necessário cast duplo pois a biblioteca externa não provê tipagem genérica adequada na versão atual
const dados = payload.raw as unknown as RespostaFormatada

5️⃣ TODOs Estruturados

Toda dívida técnica ou dúvida de negócio deixada em código deve seguir o formato // TODO:

  • Tipagem: // TODO de tipagem: Criar interface estrita para o retorno da API de listagem
  • Negócio: // TODO de regra: Validar com Produto se a taxa adicional se aplica a clientes antigos

6️⃣ Resumo das Regras

Regra Permitido Proibido
Tamanho de arquivo Até 250 linhas Acima de 250 linhas
defineComponent Obrigatório em todo .vue Componentes sem defineComponent
setup() externo — Proibido em qualquer forma
CSS externo <nome>.css vinculado ao .vue CSS inline quando ultrapassa o limite
Dispatch Table Em arquivo separado —
JSDoc Obrigatório em funções compartilhadas Omitir em funções de uso amplo
Casts as any Com biome-ignore justificado Sem comentário explicativo

7️⃣ Checklist de Validação

Antes de concluir qualquer refatoração ou adição de código:

  • O arquivo resultante tem menos de 250 linhas?
  • Funções compartilhadas têm JSDoc com @param e @returns?
  • Casts temporários têm comentário justificando?
  • TODOs estão no formato padronizado?
  • A documentação explica o porquê, não apenas o o quê?
  • defineComponent está presente em todo componente .vue?

Referências

  • Script: scripts/check-vue-linhas.sh (validação automática de tamanho)
  • Rule: .agent/rules/vue-limite-linhas.global.md (política de limite de linhas)
  • Rule: .agent/rules/typescript-sem-any.global.md (política de tipagem)
  • Skill: .agent/skills/documentar-decisao-tecnica/SKILL.md (ADRs para decisões arquiteturais)