RFC-003: Padrões de Código e Ferramentas de Linting
| Campo | Valor |
|---|---|
| Status | Draft |
| Author | Time de Tecnologia |
| Created | 2026-02-05 |
| Updated | 2026-02-05 |
| Reunião | A ser agendada |
| Deciders | Todo o time técnico |
Status
🟡 Draft - RFC em elaboração, aguardando apresentação
Contexto e Problema
Embora já tenhamos padrões de código documentados em docs/development/coding-standards.md, falta formalização de:
- Versões específicas das ferramentas obrigatórias
- Enforcement automático via pre-commit hooks e CI/CD
- Configurações padronizadas para todas as ferramentas
- Processo de atualização de ferramentas e versões
- Standards unificados para Django e FastAPI (coexistência)
Por que resolver isso agora?
- Time crescendo, necessidade de consistência maior
- Onboarding mais rápido com setup automatizado
- Reduzir tempo em code review discutindo estilo
- Prevenir bugs via análise estática
- CI/CD mais confiável com quality gates claros
Impacto de não resolver
- Código inconsistente entre desenvolvedores
- Tempo perdido em code review com debates de estilo
- Bugs evitáveis que passam sem linting
- Setup de desenvolvimento manual e propenso a erros
- Dificuldade em manter qualidade com time crescente
Documentação relacionada:
- docs/development/coding-standards.md - Padrões atuais
- docs/development/local-development.md - Setup de desenvolvimento
- docs/cicd/github-actions.md - CI/CD pipelines
- docs/testing/backend-testing.md - Standards de testes
Proposta de Solução
Padronizar e automatizar ferramentas de linting e formatting para Python (Django + FastAPI) e JavaScript/TypeScript.
Python (Django + FastAPI)
Ferramentas obrigatórias:
# pyproject.toml
[tool.black]
line-length = 100
target-version = ['py311']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.git
| \.mypy_cache
| \.venv
| migrations
)/
'''
[tool.ruff]
line-length = 100
target-version = "py311"
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
ignore = [
"E501", # line too long (handled by black)
"B008", # do not perform function calls in argument defaults
"C901", # too complex (handled case by case)
]
[tool.ruff.per-file-ignores]
"__init__.py" = ["F401"] # unused import
"tests/**/*.py" = ["S101"] # assert usage in tests is ok
[tool.ruff.isort]
known-first-party = ["app"]
[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
plugins = ["pydantic.mypy"]
[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false
Versões fixas (requirements-dev.txt):
black==24.1.1
ruff==0.1.15
mypy==1.8.0
pytest==8.0.0
pytest-cov==4.1.0
pytest-django==4.7.0 # Para Django
pytest-asyncio==0.23.3 # Para FastAPI
JavaScript/TypeScript (Frontend)
Ferramentas obrigatórias:
// .eslintrc.json
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2021,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"react/react-in-jsx-scope": "off",
"react/prop-types": "off"
},
"settings": {
"react": {
"version": "detect"
}
}
}
// .prettierrc.json
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "avoid"
}
Versões fixas (package.json):
{
"devDependencies": {
"eslint": "^8.56.0",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.2.4"
}
}
Pre-commit Hooks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-json
- id: check-merge-conflict
- id: detect-private-key
- repo: https://github.com/psf/black
rev: 24.1.1
hooks:
- id: black
language_version: python3.11
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.15
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [pydantic]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
hooks:
- id: prettier
types_or: [javascript, jsx, ts, tsx, json, yaml, markdown]
CI/CD Quality Gates
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
python-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install black ruff mypy
- name: Black check
run: black --check .
- name: Ruff check
run: ruff check .
- name: MyPy check
run: mypy app/ --ignore-missing-imports
javascript-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: ESLint check
run: npm run lint
- name: Prettier check
run: npm run format:check
Quality Gates (Bloqueantes)
Bloqueia merge se: - ❌ Black check falhar - ❌ Ruff check falhar com erros (warnings são ok) - ❌ MyPy falhar em arquivos novos/modificados - ❌ ESLint falhar - ❌ Prettier check falhar
Alternativas Consideradas
Opção 1: Pylint ao invés de Ruff
Descrição: Usar Pylint como linter principal para Python
Prós: - Mais maduro e estabelecido - Mais checks disponíveis - Ampla adoção
Contras: - Muito mais lento (10-100x mais lento que Ruff) - Configuração mais complexa - Muitos false positives - Ruff já cobre maioria dos checks importantes
Custo/Esforço: Médio
Por que não escolhemos: Ruff é muito mais rápido (escrito em Rust), cobre 90% dos casos de Pylint, e tem melhor experiência de desenvolvedor.
Opção 2: Flake8 ao invés de Ruff
Descrição: Usar Flake8 + múltiplos plugins
Prós: - Ferramenta tradicional e conhecida - Muitos plugins disponíveis - Configuração familiar
Contras: - Mais lento que Ruff - Requer múltiplos plugins (isort, flake8-bugbear, etc.) - Ruff já engloba tudo em uma ferramenta - Menos mantido ativamente
Custo/Esforço: Médio
Por que não escolhemos: Ruff oferece tudo que Flake8 oferece (e mais) em uma única ferramenta, muito mais rápida.
Opção 3: ESLint + Standard ao invés de Prettier
Descrição: Usar apenas ESLint com regras de formatação
Prós: - Uma ferramenta a menos - ESLint já faz linting
Contras: - ESLint formatting é mais lento - Prettier é opinativo (menos configuração) - Prettier suporta mais formatos (JSON, Markdown, YAML) - Comunidade converge para ESLint + Prettier
Custo/Esforço: Baixo
Por que não escolhemos: Prettier + ESLint é o padrão da indústria e oferece melhor experiência.
Opção 4: Linting manual (sem enforcement)
Descrição: Apenas documentar padrões sem ferramentas obrigatórias
Prós: - Zero overhead de ferramentas - Máxima flexibilidade - Sem falsos positivos
Contras: - Inconsistência garantida - Tempo perdido em code review - Bugs evitáveis passam - Não escala com time crescente
Custo/Esforço: Zero
Por que não escolhemos: Não é viável para time crescente. Automação é essencial para qualidade e produtividade.
Análise de Impacto
Impacto Técnico
Times afetados: - Todo time de desenvolvimento - CI/CD pipeline (novos checks) - Onboarding (novo setup)
Sistemas afetados: - Repositórios Git (pre-commit hooks) - GitHub Actions (novos workflows) - IDEs (configurações recomendadas)
Dependências: - Instalar ferramentas localmente (todos os devs) - Configurar IDEs (opcional mas recomendado) - Atualizar CI/CD pipelines
Impacto em Negócio
- ✅ Qualidade de código consistente e alta
- ✅ Code review mais rápido (menos debates de estilo)
- ✅ Onboarding mais rápido (setup automatizado)
- ✅ Menos bugs via análise estática
- ✅ Produtividade aumentada (menos tempo com estilo)
- ⚠️ Setup inicial (1-2 horas por desenvolvedor)
- ⚠️ CI/CD mais lento (+2-3 minutos por run)
Riscos Identificados
Risco 1: Falsos positivos bloqueiam desenvolvimento
- Mitigação: Configurações bem ajustadas, possibilidade de ignores pontuais (
# noqa,// eslint-disable-next-line) - Impacto: Médio
- Probabilidade: Baixa
Risco 2: Ferramentas com bugs travam CI
- Mitigação: Versões fixas, testar updates em branch separada
- Impacto: Alto
- Probabilidade: Muito Baixa
Risco 3: Resistência do time a ferramentas
- Mitigação: Demonstrar benefícios, coletar feedback, ajustar configurações
- Impacto: Médio
- Probabilidade: Baixa
Plano de Implementação
Fase 1: Configuração (Semana 1)
Tasks:
- [ ] Criar pyproject.toml com configurações Black, Ruff, MyPy
- [ ] Criar .eslintrc.json e .prettierrc.json
- [ ] Criar .pre-commit-config.yaml
- [ ] Adicionar versões fixas em requirements-dev.txt e package.json
- [ ] Atualizar .gitignore com artefatos de ferramentas
Responsável: Tech Lead
Prazo estimado: 2 dias
Fase 2: Formatação Inicial (Semana 1)
Tasks: - [ ] Rodar Black em toda a codebase - [ ] Rodar Prettier em toda a codebase - [ ] Commit de formatação: "style: apply black and prettier formatting" - [ ] Configurar git blame para ignorar commit de formatação
Responsável: Tech Lead
Prazo estimado: 1 dia
Fase 3: CI/CD (Semana 1-2)
Tasks:
- [ ] Criar workflow .github/workflows/lint.yml
- [ ] Configurar como required check em branch protection
- [ ] Testar em PR de exemplo
- [ ] Documentar processo de bypass (emergências)
Responsável: DevOps
Prazo estimado: 1 dia
Fase 4: Setup do Time (Semana 2)
Tasks: - [ ] Documentar instalação de pre-commit hooks - [ ] Criar guia de configuração de IDE (VS Code, PyCharm) - [ ] Sessão de treinamento (1h) - [ ] Pair programming para troubleshooting
Responsável: Tech Lead
Prazo estimado: 2 dias
Fase 5: Monitoramento (Semanas 3-4)
Tasks: - [ ] Monitorar adoção (pre-commit hooks instalados?) - [ ] Coletar feedback sobre falsos positivos - [ ] Ajustar configurações se necessário - [ ] Documentar casos especiais
Responsável: Todo o time
Prazo estimado: Contínuo
Métricas de Sucesso
Após 1 mês
- ✅ 100% dos PRs passam em linting checks
- ✅ 90%+ do time usa pre-commit hooks
- ✅ Zero debates de estilo em code review
- ✅ Tempo médio de code review reduzido em 20%
Após 3 meses
- ✅ Onboarding 50% mais rápido (setup automatizado)
- ✅ Bugs relacionados a type errors reduzidos em 30%
- ✅ Codebase 100% formatada consistentemente
- ✅ Time confortável com ferramentas
Após 6 meses
- ✅ Zero PRs com problemas de formatação
- ✅ Ferramentas atualizadas pelo menos 1x
- ✅ Feedback positivo do time sobre produtividade