Imports & Dependencies
Padrão cross-language pra organização de imports/use/require: ordem canônica (stdlib → third-party → local), grouping por origem com linha em branco, aliasing convention (canônicos `np`, `pd`, `tf`), wildcard imports proibidos por default, ciclos proibidos, re-export patterns (prelude/index/lib.rs), side-effect imports documentados via comentário.
Quando esta spec se aplica
Triggers primários
- Editar bloco de imports
Todos os triggers
- Adicionar import/use/require em arquivo de código
- Code review verificando ordem/grouping de imports
- Refatorar módulo legacy com imports desorganizados
- Identificar ciclo de dependências
Corpo da especificação
Spec — Imports & Dependencies
Facet Code do Koder Design.
Estende
code/languages/koda-style.kmd(que cobre só Koda) pra todas as linguagens da Stack.
R1 — Ordem canônica
Em toda linguagem, imports seguem a ordem:
- Stdlib (built-in da linguagem)
- Third-party (managed dependencies)
- Local (mesmo monorepo / mesmo módulo)
Separar grupos com uma linha em branco.
// ✅ Go
import (
"context"
"fmt"
"io"
"github.com/spf13/cobra"
"go.uber.org/zap"
"koder.dev/services/foundation/id"
"koder.dev/services/foundation/jet"
"./internal/handler"
)
# ✅ Python
import json
import os
import re
from typing import Optional
import requests
from pydantic import BaseModel
from koder.identity import Client
from koder.kompass import Workspace
from .helpers import format_email
from .models import User
// ✅ Rust
use std::collections::HashMap;
use std::fs;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use crate::config::Config;
use crate::handler::Handler;
// ✅ Dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:koder_kit/koder_kit.dart';
import 'src/screens/home.dart';
// ✅ TypeScript
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import express from 'express';
import { z } from 'zod';
import { KoderClient } from '@koder/sdk';
import { Handler } from './handler.js';
import { config } from './config.js';
R2 — Sub-grouping (Koder libs primeiro)
Dentro do grupo "third-party", separar Koder libs próprias das de terceiros — Koder primeiro:
# ✅ Sub-group Koder libs
import requests
from pydantic import BaseModel
from koder.identity import Client # Koder libs primeiro
from koder.kompass import Workspace
(Refletindo o princípio policies/reuse-first.kmd — Koder libs são
preferred sobre alternatives quando ambos servem.)
R3 — Ordem alfabética dentro do grupo
Imports alfabéticos dentro de cada grupo. Ferramentas como
isort (Python), goimports (Go), dart format fazem isso
automaticamente — configurar pra rodar no save.
R4 — Aliasing convention
Quando usar alias
- Conflito de nomes entre módulos (
from datetime import time as std_timevsfrom .util import time) - Aliases canônicos da comunidade (lista fechada — não inventar):
- Python:
import numpy as np,import pandas as pd,import tensorflow as tf,import matplotlib.pyplot as plt - JS/TS: imports default já fazem o aliasing (
import React from 'react') - Rust:
use foo::Long as Shortquando o nome se repete muito
- Python:
- Path muito longo que prejudica leitura (
use foo::bar::baz::Quux as Quux)
Quando NÃO usar alias
- Por preferência pessoal sem motivo técnico
- Pra "encurtar" sem ganho real (
import os.path as p❌) - Mascarando que é a mesma biblioteca (faz code review pior)
R5 — Wildcard imports — proibidos por default
# ❌ Polui namespace, quebra static analysis
from os import *
from .module import *
// ❌
use foo::*;
// ❌
import 'package:foo/foo.dart' show *; // (não tem essa sintaxe; ilustração)
Exceção controlada: re-exports via prelude / index.ts / lib.rs
de uma library que deliberadamente expõe um conjunto curado.
// ✅ Re-export deliberado em lib.rs
pub mod handler;
pub mod config;
pub use handler::Handler;
pub use config::Config;
// ✅ Consumer pode importar tudo dum pacote prelude
use koder::prelude::*; // explicitamente curado pelo módulo upstream
R6 — Cyclic dependencies — proibidos
Módulo A não pode importar B se B importa A direto ou transitivamente.
Quebrar via:
- Extract common — mover o que ambos precisam pra terceiro módulo
- Inverter dependência — A define interface, B implementa, C compõe (Dependency Inversion Principle)
- Late-binding — passar callback/closure em vez de import direto
CI gate (per linguagem):
- Go:
gocyclo+goimportsdetectam - Python:
pylintcycle detection - Rust: compiler já bloqueia naturalmente
- Dart:
dart analyze - JS/TS:
madge --circular
R7 — Re-export patterns (per linguagem)
| Linguagem | Arquivo | Padrão |
|---|---|---|
| Python | __init__.py |
from .module import PublicAPI |
| Rust | lib.rs / mod.rs |
pub use crate::module::PublicAPI; |
| TS | index.ts |
export { PublicAPI } from './module.js'; |
| Dart | <package>.dart (entry) |
export 'src/module.dart' show PublicAPI; |
| Go | (não tem; flat namespace) | n/a — package é a unit de export |
Princípio: re-export curado expõe API pública estável; user externo importa do entry point, não dos arquivos internos.
// ✅ Curado — public surface explícita
export 'src/sign_in_button.dart' show KoderSignInButton;
export 'src/user_badge.dart' show KoderUserBadge;
// src/internal_helper.dart não exportado — interno
R8 — Side-effect imports
Quando import existe apenas pelo side effect (não usa o nome importado), documentar com comentário:
// ✅
import (
_ "github.com/lib/pq" // register postgres driver with database/sql
)
// ✅
import 'normalize.css'; // CSS reset; no JS exports consumed
import './polyfills.js'; // patch globals before app boots
Linter falha se import sem uso e sem comentário.
R9 — Conditional imports
Casos onde import depende de plataforma ou flag:
| Linguagem | Padrão |
|---|---|
| Python | if sys.platform == 'darwin': import macos_module |
| Dart | import 'foo_io.dart' if (dart.library.html) 'foo_html.dart' |
| Rust | #[cfg(target_os = "linux")] use linux_specific; |
| Go | Build tags em arquivo separado (foo_linux.go) |
Documentar com comentário quando não-óbvio.
Anti-patterns
AP-I1 — Import everything from a module
# ❌
from numpy import *
# ✅
import numpy as np
result = np.array([1, 2, 3])
AP-I2 — Imports embaralhados
# ❌ Sem ordem nem grouping
from .helpers import foo
import os
from koder.id import Client
import json
Ferramenta auto-formata; não é decisão do dev.
AP-I3 — Import dentro de função (sem motivo)
# ❌ Sem motivo
def handler():
import json
...
# ✅ Top-of-file
import json
def handler():
...
Exceção: lazy import pra evitar circular ou heavy-weight (com comment).
AP-I4 — Re-export sem curadoria
// ❌ Re-exporta tudo, incluindo internals
pub use crate::*;
// ✅ Curado
pub use crate::handler::{Handler, HandlerError};
pub use crate::config::Config;
Audit deterministic
imports-audit.sh:
- Imports não em ordem canônica → warning (auto-fix possível)
- Wildcard import sem comment justificando → error
- Cyclic dependency detected → error (per linguagem tool)
- Side-effect import sem comment → warning
- Import dentro de função sem comment → warning
Cross-link
code/project-layout.kmd— paths refletem layoutcode/naming.kmd— package/module namingcode/languages/koda-style.kmd— Koda specificpolicies/reuse-first.kmd— Koder libs preferred
Referências
rfcs/design-RFC-001-koder-design-system.kmdspecs/code/project-layout.kmdspecs/code/naming.kmdspecs/code/languages/koda-style.kmdpolicies/design-governance.kmd