Bolhaverso

Reader

pt-br

Leia os posts do bolha.blog.

en-us

Read all posts from our users.

from Riverfount

Olá pessoal, fazia um tempo que eu estava querendo mudar a cara do meu blog, mas nunca sobrava o famigerado tempo, mas consegui.

Se por acaso você chegou aqui buscando aprender mais sobre Python, Arquitetura e Engenharia de Software bom, é só seguir para https://www.riverfount.dev.br

Obrigado a você que me acompanhou por aqui esse tempo que fiquei. Eu te espero no novo blog!!

Abraços.

 
Read more...

from @tiagojferreira@bolha.blog

Sobre o Acórdão 258/26 do TCU, o Software Livre e Universidade Pública como locus de inovação aberta e bem comum Uma ideia de protocolo para Núcleos de Inovação Tecnológica (NIT) e setor de TI, visando a priorização do licenciamento em código livre.


Introdução

O diagnóstico do Tribunal de Contas da União expresso no Acórdão 258/2026 expõe, com clareza cirúrgica, os gargalos estruturais que comprometem a gestão de Tecnologia da Informação e Comunicação nas universidades federais: déficit de pessoal, baixa interoperabilidade, fragmentação de soluções e ausência de coordenação sistêmica. Diante desse cenário, a construção de um protocolo institucional que incentive a adoção do licenciamento em software livre emerge não como uma escolha ideológica, mas como uma resposta técnica, jurídica e estratégica aos problemas identificados.

Este ensaio defende que o software livre deve ser a regra para o desenvolvimento de soluções tecnológicas nas Instituições de Ensino Superior (IES), seja pelas equipes de TI, seja por professores e alunos em projetos de pesquisa, ensino e extensão. Para tanto, examina os limites dos instrumentos tradicionais de transferência de tecnologia e cooperação, e demonstra como o licenciamento livre oferece vantagens concretas em termos de previsibilidade legal, sustentabilidade dos códigos, desburocratização do acesso e alinhamento com a função social da universidade pública e com as políticas digitais vigentes (BRASIL, 2025; 2022; 1996).


1. O Software Livre no Ordenamento Jurídico Brasileiro: Segurança e Previsibilidade

Um equívoco recorrente no debate institucional é tratar o software livre como uma excepcionalidade ou um “limbo jurídico”. A verdade é oposta: o licenciamento livre está perfeitamente integrado ao direito brasileiro, apoiando-se nos mesmos fundamentos legais que regem o software proprietário.

Softwares desenvolvidos por servidores públicos no exercício de suas funções, a titularidade pertence à universidade (art. 4º), cabendo a esta decidir sobre o licenciamento

A Lei nº 9.609/98 (Lei do Software) estabelece que o regime de proteção ao software é o do direito autoral (art. 2º, caput), assegurados ao autor direitos morais limitados (art. 2º, § 1º) e patrimoniais (art. 2º, § 5º), cuja proteção independe de registro (art. 2º, § 3º). Para softwares desenvolvidos por servidores públicos no exercício de suas funções, a titularidade pertence à universidade (art. 4º), cabendo a esta decidir sobre o licenciamento. Tanto no modelo proprietário quanto no livre, o uso do software exige contrato de licença (art. 9º). A diferença crucial reside no exercício dos direitos patrimoniais: enquanto o software proprietário utiliza licenças restritivas (EULAs) que vedam o acesso ao código-fonte, o software livre emprega licenças públicas padronizadas (GPL, MIT, Apache) que garantem as quatro liberdades fundamentais definidas pela Free Software Foundation: executar para qualquer propósito, estudar e adaptar, redistribuir cópias, e melhorar e compartilhar as melhorias.

o licenciamento de criações de relevante interesse público — hipótese que se aplica aos softwares desenvolvidos para a administração pública — somente poderá ser efetuado a título não exclusivo

Para as Instituições Científicas, Tecnológicas e de Inovação (ICTs), a Lei nº 10.973/2004 (Lei de Inovação) contempla expressamente a possibilidade de licenciamento não exclusivo e gratuito. O art. 6º, § 2º, da lei estabelece que, quando não houver exclusividade, os contratos de transferência de tecnologia e licenciamento poderão ser firmados diretamente. Já o art. 6º, § 5º, determina que o licenciamento de criações de relevante interesse público — hipótese que se aplica aos softwares desenvolvidos para a administração pública — somente poderá ser efetuado a título não exclusivo. Trata-se de previsão legal que se alinha perfeitamente ao modelo de disponibilização de software livre para a administração pública e para a sociedade. O art. 6º é só um ponto de partida, já que a totalidade dessa lei reforça os diferenciais do software livre como estratégia de transbordo da tecnologia da universidade para a sociedade.

1.1 Código aberto é obrigatório desde 2020

A obrigatoriedade do licenciamento aberto foi estabelecida pela Lei nº 14.063/2020, que em seu art. 16 determina que os sistemas desenvolvidos exclusivamente por órgãos e entidades da administração direta, autárquica e fundacional “são regidos por licença de código aberto, permitida a sua utilização, cópia, alteração e distribuição sem restrições”. As universidades e institutos federais enquadram-se perfeitamente no dispositivo, que se aplica inclusive a sistemas já em operação, ressalvadas apenas hipóteses restritas de sigilo ou componentes de terceiros. Embora tenha passado relativamente despercebida nos debates institucionais, opera uma inflexão decisiva: o que antes era faculdade conferida pela Lei de Inovação converte-se, para sistemas desenvolvidos com recursos públicos, em dever legal de abertura.

A manutenção de código fechado sem amparo nas exceções legais configuraria descumprimento de dever funcional

Para as IES, isso elimina qualquer controvérsia sobre pretensa “renúncia de receita”, como paranóicamente já se aventou — ao contrário, a manutenção de código fechado sem amparo nas exceções legais configuraria descumprimento de dever funcional. A Lei 14.063/2020, portanto, não apenas autoriza, mas impõe normativamente a compreensão do software público como bem comum, alinhando-se à função social da universidade e às recomendações do Acórdão 258/2026.

Há, portanto, previsibilidade legal plena. O protocolo que se pretende construir não precisa inventar novas figuras jurídicas; basta reconhecer e regulamentar a aplicação das já existentes, estabelecendo critérios claros para a escolha da licença mais adequada a cada contexto.


2. Limites dos Termos de Cooperação e Contratos de Transferência de Tecnologia

Os instrumentos de cooperação (como os Termos de Execução Descentralizada – TEDs) e os contratos de transferência de tecnologia mediados pelos Núcleos de Inovação Tecnológica (NITs) têm seu valor institucional, notadamente para a exploração comercial e a geração de receitas. No entanto, quando o objetivo é compartilhar soluções para a própria administração pública ou cumprir a função social da universidade, esses instrumentos revelam limitações significativas.

2.1. Natureza bilateral e negociada

Os contratos de transferência de tecnologia são, por definição, bilaterais e negociados caso a caso. Isso significa que cada novo parceiro exige um processo específico, com proposta, termo de sigilo, negociação de cláusulas e, ao final, registro no INPI para produção de efeitos legais. Trata-se de um modelo adequado para relações comerciais, mas completamente desproporcional para o compartilhamento de bens públicos digitais entre instituições que, afinal, pertencem todas ao mesmo Estado.

2.2. Burocracia como barreira ao compartilhamento

O TCU identificou que o compartilhamento efetivo de soluções ocorre apenas entre instituições que já utilizam um mesmo sistema (como na rede SIG-UFRN). Isso não é coincidência: a burocracia dos instrumentos formais de transferência desencoraja a adoção por novas instituições, que precisam vencer entraves jurídicos e administrativos para acessar uma tecnologia que, em tese, deveria estar amplamente disponível.

2.3. Código-fonte fechado ao público

Nos contratos de transferência, o código-fonte é entregue ao parceiro tecnológico, mas permanece fechado ao público em geral. Isso significa que o conhecimento financiado com recursos públicos não retorna à sociedade, não pode ser auditado por cidadãos, não pode ser estudado por alunos de outras instituições, não pode ser melhorado por desenvolvedores externos. O modelo de transferência, nesses casos, privatiza o conhecimento em vez de socializá-lo.

2.4. Dependência de fornecedores específicos

Ao transferir tecnologia com exclusividade ou condições especiais para uma única empresa, a universidade pode, inadvertidamente, criar novos monopólios e perpetuar a dependência de fornecedores específicos — exatamente o risco que o TCU aponta ao falar em “dependência de fornecedores e soluções fechadas”.


3. Vantagens do Licenciamento em Software Livre

Em contraste com as limitações acima, o licenciamento em software livre oferece vantagens estruturais que respondem diretamente aos gargalos identificados pelo TCU.

3.1. Independência e autonomia tecnológica

O software livre garante que a universidade não fique refém de um único parceiro comercial para manutenção ou evolução de um sistema. Como o código é aberto, qualquer empresa ou técnico qualificado pode prestar serviços de suporte, desenvolvimento e customização. A administração pública recupera, assim, o controle sobre sua própria tecnologia, podendo decidir soberanamente os rumos de seus sistemas estratégicos.

3.2. Compartilhamento como regra, não exceção

O maior gargalo apontado pelo TCU é a falta de compartilhamento de soluções. O licenciamento livre é a antítese desse problema. Ao publicar um código sob uma licença livre, a universidade:
- Devolve à sociedade o conhecimento financiado com recursos públicos;
- Permite que outras instituições adotem a solução sem burocracia;
- Cria as condições para que contribuições externas retornem, gerando um ciclo virtuoso de melhoria contínua.

É a realização prática do princípio constitucional da eficiência: em vez de cada universidade reconstruir a mesma roda, todas colaboram para aperfeiçoar uma roda comum.

3.3. Desburocratização do acesso

Diferentemente dos contratos de transferência, o licenciamento livre dispensa negociações caso a caso. A adesão se dá por simples aceitação dos termos da licença pública, o que reduz drasticamente custos de transação e tempo. Para o compartilhamento entre instituições públicas, essa simplicidade é crucial: um TED pode perfeitamente prever a transferência de recursos para implantação e adaptação, mas o acesso ao código propriamente dito é imediato, independente de trâmites burocráticos.

3.4. Segurança e transparência

A “liberdade de estudar” o código, uma das quatro liberdades fundamentais, permite que a universidade e a sociedade auditem os sistemas em busca de vulnerabilidades, sem depender da boa vontade de fornecedores. Num contexto de crescentes ameaças cibernéticas e da necessidade de proteção de dados (LGPD), essa capacidade de auditoria independente é um ativo de segurança nacional.

Além disso, a transparência do código é a forma mais avançada de prestação de contas à sociedade. O cidadão pode verificar, por si mesmo, como o Estado coleta, processa e armazena suas informações.

3.5. Fomento ao ecossistema local e à formação de talentos

Ao contrário do modelo de transferência que muitas vezes direciona recursos a uma única empresa (frequentemente de grande porte e sediada em centros distantes), o software livre permite que um ecossistema diversificado de prestadores de serviço locais se desenvolva. Egressos da universidade, pequenas empresas de TI da região, cooperativas de tecnologia — todos podem se capacitar para oferecer suporte e desenvolvimento sobre as plataformas abertas. Gera-se, assim, renda e conhecimento localmente, sem amarras contratuais de exclusividade.

Para os alunos, o contato com código aberto durante a graduação é uma experiência formativa inigualável. Eles não apenas aprendem a programar, mas aprendem a ler, criticar e contribuir com código real, produzido por profissionais e pesquisadores. É a universidade formando não apenas usuários de tecnologia, mas construtores de tecnologia. A continuidade dos produtos gerados pelas atividades de ensino e pesquisa, como TCCs, tende a ser favorecida com a disponibilização dos códigos, que poderão obter colaborações diversas (correções, melhorias, traduções) nos repositórios públicos especializados como Codeberg, Gitlab, Github, entre outros.


4. Aproximações e Distanciamentos: Licenciamento Livre vs. Transferência de Tecnologia

Para clareza conceitual, é útil sistematizar as diferenças entre os dois modelos:

Aspecto Licenciamento em Software Livre Contratos de Transferência de Tecnologia (via NIT) 
Natureza Jurídica Licença de uso pública e padronizada (adesão). Contrato bilateral, negociado caso a caso (solução sob medida).
Objeto da Transferência O direito de usar, estudar, modificar e distribuir o software, sob os termos da licença. O desenvolvedor mantém a titularidade. A propriedade intelectual ou o direito de explorá-la comercialmente com exclusividade ou condições especiais (espécie de “aluguel” ou “venda” dos direitos de exploração).
Código-fonte Disponível e aberto a todos (condição para as liberdades 1 e 3) . Deve ser entregue ao parceiro tecnológico, mas permanece fechado ao público. O INPI exige a entrega do código-fonte comentado para registro da transferência .
Público-alvo Toda a sociedade, outras ICTs, órgãos públicos, cidadãos. Visa o compartilhamento e o retorno social. Empresas específicas, parceiros tecnológicos selecionados para exploração comercial. Visa o retorno financeiro e o desenvolvimento econômico.
Formalização Adesão a uma licença pré-existente. Processo complexo que envolve proposta, termo de sigilo, negociação, e registro no INPI .
Registro no INPI Não é necessário para a validade da licença, mas o software pode ser registrado no INPI para segurança jurídica. O contrato de transferência de tecnologia deve ser averbado no INPI para produzir efeitos perante terceiros e para remessa de royalties ao exterior .

Esta tabela evidencia que ambos os modelos não são excludentes, mas atendem a finalidades distintas. O que se defende é que, para o desenvolvimento de software destinado à própria administração pública ou com finalidade de retorno social, o licenciamento livre deve ser a regra, reservando-se os contratos de transferência para os casos em que haja efetivo potencial de exploração comercial e parceria com o setor produtivo.


5. Argumentos para a Priorização do Software Livre

Com base no que foi exposto, apresentamos os argumentos centrais que devem fundamentar o protocolo de incentivo ao software livre nas IES:

Argumento 1: Soberania e Controle Público

Priorizar o software livre é uma decisão de soberania digital. O conhecimento produzido com verba pública permanece sob controle público, evitando a dependência de fornecedores específicos e assegurando que decisões futuras sobre sistemas estratégicos não sejam reféns de estratégias comerciais alheias ao interesse público. O código aberto é a garantia de que a universidade nunca perderá o domínio sobre suas próprias ferramentas.

Argumento 2: Eficiência e Otimização de Recursos (endereçando o déficit de pessoal)

O modelo de compartilhamento inerente ao software livre é a resposta direta ao gargalo apontado pelo TCU. Em vez de cada universidade desenvolver a mesma solução do zero com suas equipes reduzidas, um software livre bem-sucedido cria uma comunidade de cooperação onde o esforço é somado. Isso otimiza o quadro de pessoal, que pode se dedicar a adaptar e melhorar soluções existentes em vez de reconstruí-las. A duplicação de despesas é reduzida, e os recursos humanos são empregados onde realmente importam: na personalização para necessidades locais e na inovação incremental.

Argumento 3: Segurança Jurídica e Conformidade Legal

A adoção de software livre está em perfeita harmonia com o arcabouço legal brasileiro. A Lei do Software (9.609/98) e a Lei de Inovação (10.973/2004) fornecem base jurídica sólida para o licenciamento livre. Mais do que isso, o software livre é a forma mais eficaz de cumprir os princípios constitucionais da administração pública, especialmente a eficiência (compartilhando soluções) e a transparência (abrindo o código ao escrutínio público). O protocolo não precisará operar em zona cinzenta, mas sim regulamentar uma prática já amparada por lei.

Argumento 4: Função Social da Universidade e Impacto Acadêmico

O software livre é parte indissociável da missão da universidade pública. Ele permite que alunos e professores estudem e modifiquem ferramentas de ponta, contribuindo para uma formação crítica e não meramente instrumental. Ao liberar o código de projetos de pesquisa, TCCs, dissertações e extensão, a universidade multiplica o impacto social do seu conhecimento, permitindo que ele seja reaproveitado, testado e melhorado pela sociedade. Gera-se um ciclo virtuoso de inovação aberta e colaborativa que aproxima a academia da comunidade e forma cidadãos capacitados para participar ativamente da construção do futuro digital do país.

Argumento 5: Fomento ao Desenvolvimento Local e Desconcentração de Recursos

O software livre viabiliza um ecossistema diversificado de prestadores de serviço locais. Pequenas empresas de TI, cooperativas, startups de base tecnológica — todas podem oferecer suporte, desenvolvimento e capacitação sobre plataformas abertas. Isso desconcentra recursos, que não ficam restritos a grandes fornecedores nacionais ou internacionais, e fortalece economias regionais. A universidade, ao adotar software livre, atua como indutora do desenvolvimento local e da geração de emprego e renda qualificados em seu entorno.


6. Diretrizes para o Protocolo

À guisa de conclusão, propomos que o protocolo institucional contemple as seguintes diretrizes:

1. Regra geral de abertura: todo software desenvolvido com recursos públicos ou por servidores públicos no exercício de suas funções será disponibilizado sob licença de software livre, salvo justificativa técnica ou legal aprovada pela instância competente.

2. Orientação e capacitação: os Núcleos de Inovação Tecnológica (NITs) deverão ser capacitados para orientar desenvolvedores sobre as diferentes licenças livres e seus respectivos impactos, auxiliando na escolha da mais adequada a cada projeto.

3. Repositório institucional: a universidade manterá repositório público de código, integrado a plataformas nacionais (como a Vitrine MEC) e internacionais, com governança clara e mecanismos para recebimento de contribuições externas.

4. Incentivos acadêmicos: projetos de pesquisa, TCCs, dissertações e teses que resultarem em software funcional serão estimulados a publicá-lo em repositório aberto, podendo receber certificação ou distinção acadêmica.

5. Compartilhamento interinstitucional: nos termos de cooperação com outras ICTs, o licenciamento livre será a modalidade preferencial, ressalvados os casos de efetivo potencial comercial que justifiquem modelo diverso.

6. Monitoramento e prestação de contas: a universidade manterá indicadores de adoção de software livre (número de projetos abertos, repositórios publicados, contribuições recebidas), a serem incluídos nos relatórios de gestão encaminhados aos órgãos de controle.


Conclusão

O Acórdão 258/2026 do TCU escancara uma verdade incômoda: apesar dos esforços individuais, as universidades federais operam em regime de isolamento tecnológico, recomprando soluções e reconstruindo o que já foi construído, enquanto perdem seus quadros mais qualificados para o mercado. O software livre não é uma panaceia, mas é, sem dúvida, parte fundamental da resposta.

Ele oferece um caminho juridicamente seguro, tecnicamente viável e estrategicamente acertado para superar os gargalos identificados. Permite compartilhar em vez de isolar, colaborar em vez de competir, abrir em vez de fechar. Mais do que isso: realiza a função social da universidade pública, que é produzir conhecimento e devolvê-lo à sociedade na forma de bens comuns, acessíveis a todos e passíveis de melhoria contínua por todos.

O protocolo que se propõe não é um ato de fé no software livre, mas uma construção racional baseada em evidências — as evidências do TCU sobre o que não está funcionando — e em fundamentos legais sólidos. É um instrumento para a universidade pública recuperar controle sobre sua própria tecnologia, otimizar seus recursos escassos e cumprir, com excelência, sua missão de ensinar, pesquisar e estender à sociedade os frutos do conhecimento que produz.

O software desenvolvido com dinheiro público, por servidores públicos, para atender a necessidades públicas, deve ser, por definição, um bem público. O licenciamento livre é a ferramenta jurídica que transforma esse princípio em realidade.

Referências

BRASIL. Ministério da Ciência, Tecnologia e Inovação. Plano Brasileiro de Inteligência Artificial 2025-2028 (PBIA). Brasília, DF: MCTI, 2025.

BRASIL. Tribunal de Contas da União. Acórdão nº 258/2026 – TCU – Plenário. Acompanhamento. Universidades Federais. Avaliação da governança, do planejamento e do ambiente de Tecnologia da Informação e Comunicação (TIC). Relator: Ministro Augusto Nardes. Sessão de 4 de fevereiro de 2026. Disponível em: https://pesquisa.apps.tcu.gov.br/redireciona/acordao-completo/ACORDAO-COMPLETO-2735020. Acesso em: 20 fev. 2026.

BRASIL. Decreto nº 12.198, de 24 de setembro de 2024. Institui a Estratégia Federal de Governo Digital para o período de 2024 a 2027. Diário Oficial da União: seção 1, Brasília, DF, 25 set. 2024.

BRASIL. Lei nº 14.063, de 23 de setembro de 2020. Dispõe sobre o uso de assinaturas eletrônicas em interações com entes públicos, em atos de pessoas jurídicas e em questões de saúde e sobre as licenças de softwares desenvolvidos por entes públicos; e altera a Lei nº 9.096, de 19 de setembro de 1995, a Lei nº 5.991, de 17 de dezembro de 1973, e a Medida Provisória nº 2.200-2, de 24 de agosto de 2001. Diário Oficial da União: seção 1, Brasília, DF, ano 157, n. 184, p. 1-4, 24 set. 2020. Disponível em: https://www.planalto.gov.br/ccivil_03/_ato2019-2022/2020/lei/l14063.htm. Acesso em: 26 fev. 2026.

BRASIL. Ministério da Economia. Secretaria Especial de Desburocratização, Gestão e Governo Digital. Secretaria de Governo Digital. Instrução Normativa SGD/ME nº 94, de 23 de dezembro de 2022. Dispõe sobre o processo de contratação de soluções de Tecnologia da Informação e Comunicação pelos órgãos e entidades integrantes do Sistema de Administração dos Recursos de Tecnologia da Informação – SISP do Poder Executivo Federal. Diário Oficial da União: seção 1, Brasília, DF, 26 dez. 2022.

BRASIL. Ministério da Gestão e da Inovação em Serviços Públicos. Secretaria de Governo Digital. Instrução Normativa SGD/MGI nº 6, de 28 de fevereiro de 2023. Dispõe sobre a contratação de soluções de Tecnologia da Informação e Comunicação pelos órgãos e entidades integrantes do Sistema de Administração dos Recursos de Tecnologia da Informação – SISP do Poder Executivo Federal. Diário Oficial da União: seção 1, Brasília, DF, 1º mar. 2023.

FREE SOFTWARE FOUNDATION (FSF). O que é software livre? Disponível em: https://www.gnu.org/philosophy/free-sw.pt-br.html. Acesso em: 20 fev. 2026.

 
Read more...

from in.versos

Hoje sou tudo o que fui — ontem — e jamais serei.

Hoje sou beijo e mordida, lábios e dentes, olhos e pele.

Hoje sou saudade, esperança e aflição.

Hoje sou escarro, lágrimas e gritos.

Hoje sou feio, mediano e bonito.

Hoje sou — porque.

Amanhã não sei: talvez eu seja teu amor e tu o meu; talvez eu não seja mais ninguém.

 
Leia mais...

from Riverfount

Se você escreve Python há algum tempo, já usou decorators sem perceber. O @app.route do Flask, o @pytest.mark.parametrize, o @dataclass da stdlib, o @property nativo da linguagem — todos são decorators. Eles aparecem em todo framework relevante do ecossistema, mas a maioria dos recursos disponíveis explica como usar sem explicar por que funciona.

Este artigo corrige isso.

A ideia aqui não é ensinar a sintaxe do @. É mostrar o mecanismo embaixo: o que Python faz quando encontra esse símbolo, como construir um decorator do zero com segurança e como evitar as armadilhas que só aparecem em produção.


1. Pré-requisito: Funções São Objetos de Primeira Classe

Antes de entender decorators, é preciso internalizar um conceito que Python respeita de forma consistente: funções são objetos como qualquer outro.

Isso significa que uma função pode ser atribuída a uma variável, passada como argumento para outra função, e retornada como resultado de uma chamada. Se isso parece óbvio, bem. Mas as consequências disso são o alicerce inteiro do decorator pattern.

Funções podem ser atribuídas a variáveis:

def saudacao() -> str:
    return "Olá!"

outra_referencia = saudacao   # sem parênteses — não estamos chamando, estamos referenciando
print(outra_referencia())     # "Olá!"

Funções podem ser passadas como argumento:

def executar(func) -> None:
    print("Antes")
    func()
    print("Depois")

executar(saudacao)
# Antes
# Olá!
# Depois

Funções podem ser retornadas por outras funções:

def criar_saudacao(nome: str):
    def mensagem() -> str:
        return f"Olá, {nome}!"   # captura 'nome' do escopo externo
    return mensagem  # retorna a função, não o resultado

ola_vicente = criar_saudacao("Vicente")
print(ola_vicente())   # "Olá, Vicente!" — mesmo após criar_saudacao() ter retornado

Esse último exemplo tem um nome técnico: closure. A função interna mensagem “fecha sobre” a variável nome do escopo externo e a mantém viva mesmo depois que criar_saudacao terminou de executar. O Python preserva esse contexto enquanto houver uma referência à função interna.

Closures são o mecanismo que permite decorators funcionarem. Quando você entende closures, a mecânica do @ deixa de ser mágica e passa a ser consequência natural.


2. A Mecânica do Decorator — Desvendando o @

Com closures claras, o decorator se torna trivial de entender: @decorator é açúcar sintático para uma atribuição.

@meu_decorator
def funcao() -> None:
    ...

O Python transforma isso exatamente em:

def funcao() -> None:
    ...
funcao = meu_decorator(funcao)

É tudo. Não existe nenhuma magia adicional. O símbolo @ instrui o interpretador a passar a função definida logo abaixo como argumento para meu_decorator e a reatribuir o resultado de volta ao mesmo nome.

Para deixar isso concreto, veja o primeiro decorator possível — sem usar @, para tornar o mecanismo explícito:

def logar(func):
    def wrapper():
        print(f"Chamando {func.__name__}...")
        func()
        print(f"{func.__name__} concluída.")
    return wrapper

def processar() -> None:
    print("Processando pedido.")

# Sem @: reatribuição explícita
processar = logar(processar)
processar()
# Chamando processar...
# Processando pedido.
# processar concluída.

Agora a mesma coisa com a sintaxe @ — o resultado é idêntico:

@logar
def processar() -> None:
    print("Processando pedido.")

processar()
# Chamando processar...
# Processando pedido.
# processar concluída.

O @ é apenas uma forma mais limpa de escrever processar = logar(processar). Reconhecer isso é o que permite raciocinar sobre qualquer decorator, não importa o quão complexo ele pareça.


3. Anatomia de um Decorator Bem Formado

O exemplo acima funciona, mas tem um problema: só aceita funções sem argumentos. Em produção, os decorators precisam ser transparentes — funcionar com qualquer assinatura de função, independentemente de quantos parâmetros ela receba.

Este é o template canônico:

import functools

def meu_decorator(func):
    @functools.wraps(func)  # (a) preserva a identidade da função original
    def wrapper(*args, **kwargs):  # (b) aceita qualquer assinatura
        # (c) lógica executada antes da função original
        resultado = func(*args, **kwargs)   # (d) chama a função original com seus argumentos
        # (e) lógica executada depois
        return resultado  # (f) retorna o valor original sem modificá-lo
    return wrapper  # (g) retorna o wrapper — não chama, retorna

Cada ponto merece atenção:

(a) @functools.wraps(func) preserva os metadados da função original no wrapper. O motivo completo merece uma seção própria — e vai ter uma logo adiante.

(b) *args, **kwargs garante que o wrapper aceita qualquer combinação de argumentos posicionais e nomeados, repassando-os intactos para a função original. Sem isso, o decorator só funciona com funções de assinatura idêntica à do wrapper.

© e (e) São os pontos onde a lógica do decorator vive: logging, validação, timing, cache — tudo entra aqui.

(d) func(*args, **kwargs) chama a função original com os mesmos argumentos recebidos. Note que a variável func vem do escopo externo — isso é a closure em ação.

(f) return resultado é crítico. Um decorator que não retorna o valor da função original “engole” o retorno silenciosamente. Se processar_pedido retorna uma lista de itens e o decorator não faz return resultado, o chamador recebe None.

(g) return wrapper está fora do corpo do wrapper. O decorator retorna a função wrapper — não a chama. É essa distinção que faz o mecanismo funcionar: ao escrever @meu_decorator, Python substitui o nome da função pelo wrapper retornado aqui.

Exemplo completo com timer:

import time
import functools

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        inicio = time.perf_counter()
        resultado = func(*args, **kwargs)
        fim = time.perf_counter()
        print(f"{func.__name__!r} executou em {fim - inicio:.6f}s")
        return resultado
    return wrapper

@timer
def processar_pedidos(n: int) -> list[int]:
    """Simula o processamento de uma lista de pedidos."""
    return list(range(n))

itens = processar_pedidos(100_000)
# 'processar_pedidos' executou em 0.004312s

time.perf_counter() é preferível a time.time() para medições de performance: tem resolução mais alta e não sofre ajustes de relógio do sistema.


4. O Problema da Identidade — Por que functools.wraps É Obrigatório

Há um detalhe sutil que cobra um preço alto quando ignorado. Observe:

def log(func):
    def wrapper(*args, **kwargs):  # sem @functools.wraps
        return func(*args, **kwargs)
    return wrapper

@log
def calcular_total(pedido: dict) -> float:
    """Calcula o valor total de um pedido com impostos."""
    ...

print(calcular_total.__name__)   # 'wrapper'  ← errado
print(calcular_total.__doc__)    # None        ← errado

Após a decoração, calcular_total aponta para o objeto wrapper. Sem nenhum cuidado adicional, __name__, __doc__, __annotations__ e outros atributos são os do wrapper — não os da função original. O nome que aparece em stack traces, em ferramentas de documentação automática como Sphinx, em pytest markers e no help() interativo é wrapper.

Em um projeto com dezenas de funções decoradas, todo stack trace em produção vai apontar para wrapper em vez de indicar a função real com problema. O custo de debugging aumenta desnecessariamente.

functools.wraps resolve isso. Ele é um decorator aplicado ao wrapper que copia os atributos relevantes da função original:

def log(func):
    @functools.wraps(func)    # copia os metadados de func para wrapper
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

@log
def calcular_total(pedido: dict) -> float:
    """Calcula o valor total de um pedido com impostos."""
    ...

print(calcular_total.__name__)   # 'calcular_total'  ← correto
print(calcular_total.__doc__)    # 'Calcula o valor...'  ← correto

Internamente, functools.wraps é um atalho para functools.update_wrapper(wrapper, func). Os atributos transferidos são:

Atributo O que representa
__name__ Nome da função — aparece em stack traces e repr
__qualname__ Nome qualificado — inclui classe e módulo, para contexto exato
__doc__ Docstring — essencial para help(), Sphinx e IDEs
__module__ Módulo de origem — identifica onde a função foi definida
__annotations__ Type hints — necessário para mypy e ferramentas de análise estática
__dict__ Atributos customizados — preserva metadados adicionados à função
__wrapped__ Referência direta à função original — adicionado pelo wraps

O atributo __wrapped__ merece destaque: ele permite “desembrulhar” a cadeia de decorators e acessar a função original diretamente, o que é útil em testes e introspecção.

print(calcular_total.__wrapped__)   # <function calcular_total at 0x...>

A regra é simples: todo decorator deve usar @functools.wraps(func) no wrapper interno, sem exceção. O custo é zero, o benefício é real.


5. Decorators com Argumentos — A Fábrica de Decorators

Até aqui, os decorators recebem apenas a função como argumento. Mas muitos dos decorators mais úteis precisam de configuração: @retry(max_tentativas=3), @cache(ttl=60), @permissao_requerida("admin").

Ao adicionar parênteses ao decorator, o comportamento muda completamente — e é aqui que a maioria dos tutoriais perde o leitor.

A confusão vem do seguinte: @repetir(vezes=3) não está chamando um decorator. Está chamando uma fábrica de decorator — uma função que, ao ser chamada com os argumentos de configuração, retorna o decorator de verdade.

A estrutura tem três camadas:

import functools

def repetir(vezes: int):  # ← camada 1: fábrica — recebe os argumentos
    def decorator(func):   # ← camada 2: decorator — recebe a função
        @functools.wraps(func)
        def wrapper(*args, **kwargs):  # ← camada 3: wrapper — executa em runtime
            for _ in range(vezes):
                resultado = func(*args, **kwargs)
            return resultado
        return wrapper
    return decorator  # fábrica retorna o decorator

@repetir(vezes=3)
def notificar(mensagem: str) -> None:
    print(f"[NOTIF] {mensagem}")

notificar("pedido aprovado")
# [NOTIF] pedido aprovado
# [NOTIF] pedido aprovado
# [NOTIF] pedido aprovado

Para entender o que acontece passo a passo, expanda a sintaxe @:

# @repetir(vezes=3) se desdobra em:

_decorator = repetir(vezes=3)  # step 1: chama a fábrica, obtém o decorator
notificar = _decorator(notificar)  # step 2: aplica o decorator à função

A variável vezes fica capturada pela closure do wrapper, que a usa em cada chamada de notificar.

A regra para identificar quantas camadas um decorator precisa é direta: decorator sem parênteses = uma função que recebe func; decorator com parênteses = uma função que recebe os argumentos e retorna uma função que recebe func.


6. Stacking — Empilhando Decorators e a Ordem de Execução

Python permite empilhar múltiplos decorators sobre uma mesma função. A ordem em que eles aparecem determina o comportamento — e errar essa ordem pode introduzir bugs silenciosos que só aparecem em produção.

@decorator_a  # aplicado por último, envolve o resultado de decorator_b
@decorator_b  # aplicado primeiro, envolve a função original
def minha_funcao():
    ...

# Equivalente exato:
minha_funcao = decorator_a(decorator_b(minha_funcao))

A regra de ouro: a aplicação é de baixo para cima (o decorator mais próximo da função é aplicado primeiro), mas a execução em runtime é de cima para baixo (o decorator mais externo executa primeiro).

Para tornar isso concreto, considere dois decorators em um endpoint de API:

import functools

def logar(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(f"[LOG] Chamando {func.__name__!r}")
        resultado = func(*args, **kwargs)
        print(f"[LOG] {func.__name__!r} concluída")
        return resultado
    return wrapper

def autenticar(func):
    @functools.wraps(func)
    def wrapper(usuario: str, *args, **kwargs):
        if usuario != "admin":
            raise PermissionError(f"Acesso negado para '{usuario}'")
        return func(usuario, *args, **kwargs)
    return wrapper

Cenário A — @logar acima de @autenticar:

@logar
@autenticar
def obter_relatorio(usuario: str) -> dict:
    return {"relatorio": "dados sensíveis"}

obter_relatorio("convidado")
# [LOG] Chamando 'obter_relatorio'   ← loga antes de verificar permissão
# PermissionError: Acesso negado para 'convidado'

O log registra a tentativa de acesso mesmo quando o usuário não tem permissão. Em alguns sistemas, isso é o comportamento correto — registrar toda tentativa, incluindo as negadas.

Cenário B — @autenticar acima de @logar:

@autenticar
@logar
def obter_relatorio(usuario: str) -> dict:
    return {"relatorio": "dados sensíveis"}

obter_relatorio("convidado")
# PermissionError: Acesso negado para 'convidado'
# (sem log — a exceção ocorre antes do log ser atingido)

Aqui, a autenticação bloqueia antes do log registrar qualquer coisa. Apenas chamadas autenticadas chegam ao log.

Ambos os comportamentos podem ser desejados, dependendo do requisito. O ponto é que a ordem define o comportamento, e não há nada no código que sinalize a diferença visualmente além da posição do @. É uma decisão arquitetural que precisa ser documentada.


7. Decorators Baseados em Classe — Quando o Estado Importa

Até agora, todos os decorators foram funções. Mas Python permite usar classes como decorators também — e elas se tornam a escolha certa quando o decorator precisa manter estado entre chamadas.

Um contador de invocações é o exemplo mais direto:

import functools

class Contador:
    def __init__(self, func) -> None:
        functools.update_wrapper(self, func)
        self.func = func
        self.chamadas: int = 0

    def __call__(self, *args, **kwargs):
        self.chamadas += 1
        return self.func(*args, **kwargs)

@Contador
def buscar_usuario(user_id: int) -> dict:
    """Busca dados de um usuário pelo ID."""
    return {"id": user_id}

buscar_usuario(1)
buscar_usuario(2)
buscar_usuario(3)
print(f"Total de chamadas: {buscar_usuario.chamadas}")   # Total de chamadas: 3

O @Contador sobre buscar_usuario é equivalente a buscar_usuario = Contador(buscar_usuario). O construtor __init__ recebe a função, __call__ é executado cada vez que a função decorada é chamada, e o estado (self.chamadas) persiste no objeto.

O que update_wrapper realmente faz numa instância de classe

Aqui vale parar e ser preciso, porque há uma nuance importante que a maioria dos tutoriais ignora.

functools.update_wrapper(self, func) copia atributos como __name__, __qualname__, __doc__ e __annotations__ da função original para o objeto instância — não para a classe Contador. Isso significa que a introspecção programática funciona corretamente:

print(buscar_usuario.__name__)      # 'buscar_usuario'  ← correto
print(buscar_usuario.__doc__)       # 'Busca dados de um usuário pelo ID.'  ← correto
print(buscar_usuario.__wrapped__)   # <function buscar_usuario at 0x...>  ← correto

Porém, o __repr__ padrão de um objeto em Python é gerado pela classe, não pela instância. E a classe Contador não sabe nada sobre __name__ — ela simplesmente herda o __repr__ de object, que produz:

repr(buscar_usuario)
# <__main__.Contador object at 0x7f3a4c2b1d90>

Não <function buscar_usuario at 0x...>, como seria com um decorator de função. O update_wrapper não tem como alterar isso: atributos de instância não têm efeito sobre o __repr__ padrão da classe.

Para fins práticos do dia a dia — pytest, mypy, Sphinx, logging, stack traces — isso raramente é problema: todas essas ferramentas usam __name__ e __qualname__ diretamente, e esses atributos estão corretos. O __repr__ entra em cena principalmente no REPL interativo e em sessões de debug — exatamente onde um repr que “mente” pode confundir mais do que ajudar.

A solução correta: __repr__ que comunica a realidade

O caminho certo não é imitar o repr de uma função — é comunicar a natureza real do objeto, incluindo o estado que só um decorator de classe pode ter:

import functools

class Contador:
    def __init__(self, func) -> None:
        functools.update_wrapper(self, func)
        self.func = func
        self.chamadas: int = 0

    def __call__(self, *args, **kwargs):
        self.chamadas += 1
        return self.func(*args, **kwargs)

    def __repr__(self) -> str:
        return (
            f"<Contador decorator de {self.func.__qualname__!r} "
            f"— {self.chamadas} chamada(s)>"
        )

@Contador
def buscar_usuario(user_id: int) -> dict:
    """Busca dados de um usuário pelo ID."""
    return {"id": user_id}

buscar_usuario(1)
buscar_usuario(2)

repr(buscar_usuario)
# <Contador decorator de 'buscar_usuario' — 2 chamada(s)>

Isso honra os dois requisitos ao mesmo tempo: __name__ e __qualname__ continuam disponíveis para introspecção programática via update_wrapper, e o repr comunica o que o objeto realmente é — um decorator com estado — em vez de fingir ser uma função simples.

A distinção importa especialmente quando o decorator carrega estado observável. Um repr que oculta chamadas, cache, ou qualquer outro estado interno priva o desenvolvedor de informação útil no momento em que ele mais precisa dela: durante o debug.

Quando usar cada abordagem:

Situação Escolha
Comportamento puro sem estado (log, timer, validação) Decorator de função
Estado entre chamadas (contador, cache, rate limiter) Decorator de classe com __repr__ explícito
Lógica configurável via argumentos Fábrica de decorators

8. Padrões de Produção — Exemplos Prontos para Usar

Com a mecânica compreendida, esta seção apresenta três decorators que resolvem problemas reais e podem ser adaptados diretamente em projetos.

8.1 Retry Automático com Backoff

Chamadas a serviços externos falham. Redes instáveis, timeouts, rate limiting — são situações normais em produção. Um decorator de retry encapsula a lógica de re-tentativa sem poluir o código de negócio:

import time
import functools

def retry(max_tentativas: int = 3, delay: float = 1.0, excecoes: tuple = (Exception,)):
    """
    Tenta executar a função até max_tentativas vezes.
    Aguarda delay segundos entre cada tentativa.
    Levanta a exceção original após esgotar as tentativas.
    """
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for tentativa in range(1, max_tentativas + 1):
                try:
                    return func(*args, **kwargs)
                except excecoes as e:
                    if tentativa == max_tentativas:
                        raise
                    print(
                        f"[RETRY] {func.__name__!r} — tentativa {tentativa}/{max_tentativas} "
                        f"falhou: {e}. Aguardando {delay}s..."
                    )
                    time.sleep(delay)
        return wrapper
    return decorator

@retry(max_tentativas=3, delay=0.5, excecoes=(ConnectionError, TimeoutError))
def chamar_api_pagamentos(payload: dict) -> dict:
    """Envia um pagamento para o processador externo."""
    ...

O parâmetro excecoes permite especificar quais exceções devem acionar o retry. Erros de programação como ValueError ou TypeError não devem ser re-tentados — por isso o padrão não é Exception para tudo.

8.2 Cache por Memoização

Funções que recebem os mesmos argumentos e produzem sempre o mesmo resultado são candidatas à memoização. O decorator abaixo ilustra a lógica antes de introduzir a solução da stdlib:

import functools

def memoizar(func):
    """
    Armazena resultados anteriores indexados pelos argumentos.
    Evita recomputação para entradas já vistas.
    """
    cache: dict = {}

    @functools.wraps(func)
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@memoizar
def fibonacci(n: int) -> int:
    """Calcula o n-ésimo número de Fibonacci."""
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(40))   # instantâneo — sem memoização seria exponencial

Em projetos reais, use @functools.lru_cache(maxsize=128) ou @functools.cache (Python 3.9+) — são implementações da stdlib com controle de tamanho, thread safety e suporte a kwargs. O decorator manual acima serve para compreender o mecanismo antes de usar a versão pronta.

8.3 Validação de Argumentos

Validações de entrada que se repetem em múltiplas funções são candidatas a serem extraídas para um decorator. Isso reduz duplicação e, como consequência direta, reduz a complexidade ciclomática de cada função — o que já discutimos no artigo sobre Radon.

import functools

def validar_positivo(func):
    """
    Garante que o primeiro argumento posicional é um número positivo.
    Levanta ValueError com mensagem descritiva caso contrário.
    """
    @functools.wraps(func)
    def wrapper(valor: float, *args, **kwargs):
        if valor <= 0:
            raise ValueError(
                f"{func.__name__!r} exige um valor positivo. "
                f"Recebido: {valor!r}"
            )
        return func(valor, *args, **kwargs)
    return wrapper

@validar_positivo
def calcular_desconto(preco: float, percentual: float) -> float:
    """Calcula o valor após aplicar o desconto."""
    return preco * (1 - percentual / 100)

@validar_positivo
def calcular_frete(peso_kg: float) -> float:
    """Calcula o custo de frete baseado no peso."""
    return peso_kg * 3.5

calcular_desconto(-10.0, 5)
# ValueError: 'calcular_desconto' exige um valor positivo. Recebido: -10.0

Cada função de negócio ficou com uma única responsabilidade — o decorator cuidou da guarda de entrada.


9. Armadilhas Comuns — O que Costuma Dar Errado

Engolir o retorno da função original

# Errado — não retorna o resultado
def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)   # ← sem return
    return wrapper

@log
def somar(a: int, b: int) -> int:
    return a + b

resultado = somar(2, 3)
print(resultado)   # None — o valor foi perdido silenciosamente

O Python não avisa sobre isso. A função executa normalmente, mas o valor retornado some. Sempre use return func(*args, **kwargs) ou armazene em variável antes de retornar.

Esquecer functools.wraps

Já detalhado na seção 4. O custo de depurar stack traces cheios de wrapper em produção é muito maior do que adicionar uma linha ao decorator.

Decorar métodos de instância sem considerar self

Decorators que inspecionam o primeiro argumento precisam de atenção ao ser aplicados a métodos:

def validar_id(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # args[0] aqui é 'self', não o primeiro argumento real do método
        user_id = args[1] if len(args) > 1 else kwargs.get("user_id")
        if not isinstance(user_id, int) or user_id <= 0:
            raise ValueError(f"user_id inválido: {user_id!r}")
        return func(*args, **kwargs)
    return wrapper

class UserService:
    @validar_id
    def buscar(self, user_id: int) -> dict:
        ...

O self entra como args[0], empurrando os argumentos reais para args[1] em diante. Decorators de função que assumem args[0] como primeiro argumento do usuário quebram silenciosamente ao serem aplicados a métodos.

Stacking na ordem errada

Como demonstrado na seção 6, inverter a posição de @autenticar e @logar produz comportamentos diferentes. Sem um comentário que documente a intenção, a ordem parece arbitrária para quem lê o código depois.


10. Checklist de Boas Práticas

# Prática Por quê
1 Sempre use @functools.wraps(func) no wrapper interno Preserva identidade da função em stack traces, docs e ferramentas
2 Use *args, **kwargs no wrapper Garante compatibilidade com qualquer assinatura de função
3 Sempre retorne resultado = func(...) / return resultado Evita engolir retornos silenciosamente
4 Prefira decorator de função para comportamento puro Mais simples, sem overhead de classe
5 Use decorator de classe quando precisar de estado entre chamadas self é o lugar natural para manter estado
6 Documente o decorator com docstring Descreva o que ele adiciona, não o que a função faz
7 Em stacking, coloque o decorator mais específico mais próximo da função Torna a cadeia de transformações previsível
8 Especifique as exceções no retry, não use Exception para tudo Evita re-tentativas em erros de programação
9 Em decorators de classe, use functools.update_wrapper(self, func) Equivalente ao @wraps para instâncias
10 Documente a ordem em stacking quando ela for semanticamente relevante Quem lê o código não deve ter que raciocinar sobre a ordem

11. Conclusão

Decorators não são mágica. São closures com açúcar sintático — e a sintaxe @ é apenas uma forma elegante de escrever funcao = decorator(funcao).

Entender isso abre um caminho direto para duas habilidades práticas: saber ler qualquer decorator existente em frameworks e bibliotecas, e saber construir os seus com a estrutura correta desde o início.

Há uma conexão direta com outros princípios já explorados aqui no blog. O functools.wraps é a materialização do princípio de nomear pelo propósito — sem ele, __name__ mente para toda ferramenta que depende do nome da função. E decorators que extraem lógica transversal — retry, log, validação, cache — reduzem a complexidade ciclomática das funções de negócio, exatamente o que o radon mediria como melhoria no artigo sobre CC.

Um decorator bem escrito é invisível: a função de negócio comunica sua intenção, e o comportamento adicional está encapsulado, testável e reutilizável. É código que se explica por si só — e isso é poder puro na engenharia de software.

Se este artigo te fez repensar como você aplica comportamento transversal no seu código, compartilhe o decorator mais criativo que já escreveu: @riverfount@bolha.us

 
Read more...

from vitu

Foi promulgada, em 17 de setembro de 2025, a lei nº 15.211, a qual ficou conhecida como “ECA Digital” ou “Lei Felca”, trazendo incertezas e preocupações para administradores de instâncias do Fediverso brasileiro, especialmente quanto a quais medidas devem ser adotadas e quais os riscos a que estarão sujeitos. O objetivo deste texto, longe de trazer soluções plenas, é colaborar com algumas reflexões, questionamentos e, dentro do possível, sugestões para minimizar potenciais riscos.

Vamos então, gradualmente, passando pelos pontos que considerei de principal relevância para as redes federadas como um todo.

Aplicabilidade do ECA Digital às redes federadas

Antes de tudo e ponto de extrema importância nessa lei, temos a problemática quanto ao que significa ser um produto ou serviço “direcionado a crianças e a adolescentes ou de acesso provável por eles“. Infelizmente a própria lei não traz uma definição clara e objetiva a esse respeito, de forma que ficaremos dependendo, como em diversos outros pontos, de uma regulamentação posterior pela “autoridade administrativa autônoma de proteção dos direitos de crianças e de adolescentes”, por atos do Poder Executivo e pela jurisprudência que surgir a partir da aplicação efetiva da lei em 17 de março de 2026 (Art. 41-A).

Também é válido questionar o quanto essa lei será aplicável às redes federadas e em que medida, tendo em vista que o seu art. 2º, III define rede social como uma

aplicação de internet que tem como principal finalidade o compartilhamento e a disseminação, pelos usuários, de opiniões e informações veiculadas por textos ou arquivos de imagens, sonoros ou audiovisuais, em uma única plataforma, por meio de contas conectadas ou acessíveis de forma articulada, permitida a conexão entre usuários; (grifo meu)

A dinâmica própria das redes federadas e suas diversas instâncias abrem questionamentos, portanto, sobre o quanto ela pode ser considerada uma rede social, nos termos da lei 15.211/2025, uma vez que, apesar de possibilitar a conexão entre os usuários, essa não ocorre por meio de “uma única plataforma”.

Voltando a atenção ao que torna essa comunicação possível, devido ao conteúdo do § 2º do referido art. 2º, o protocolo ActivityPub não deve ser considerado, por si só, um “produto ou serviço de tecnologia da informação”, uma vez que prescreve o parágrafo:

§ 2º Para os fins desta Lei, não são consideradas produtos ou serviços de tecnologia da informação as funcionalidades essenciais para o funcionamento da internet, como os protocolos e os padrões técnicos abertos e comuns que permitem a interconexão entre as redes de computadores que compõem a internet. (grifo meu)

Não deve, portanto, o protocolo em si ser considerado mesmo uma rede social ou receber qualquer tipo de sanção determinada pela lei, mas a dúvida quanto às instâncias permanece.

Atribuições do órgão regulador

Em vários trechos da lei, é mencionada a “autoridade administrativa autônoma de proteção dos direitos de crianças e de adolescentes no ambiente digital”. Como regulamentado pelo Decreto nº 12.622, essa função fiscalizatória foi delegada à Agência Nacional de Proteção de Dados (ANPD), a qual poderá fazer recomendações e orientações para o cumprimento da lei (art. 6º, § 3º); será a responsável por regular e promover soluções técnicas para verificação de idade (art. 11); e fiscalizará o cumprimento da lei, podendo editar normas complementares (art. 34).

Assim sendo, é possível esperar que haja uma postura propositiva por parte da ANPD, chegando a colaborar com soluções para o devido cumprimento da legislação. Entretanto, é algo que somente será passível de confirmação com a sua entrada em vigor.

Proporcionalidade de medidas sancionatórias

Por todo o corpo da legislação, é possível vislumbrar uma preocupação com os princípios jurídicos da proporcionalidade e razoabilidade para a análise dos casos concretos e para a aplicação de sanções. Destaco o art. 34, § 2º, que trata da função fiscalizatória da ANPD:

Art. 34. § 2º Nas atividades previstas no caput deste artigo [fiscalização do cumprimento da lei], a autoridade competente deverá observar as assimetrias regulatórias e adotar abordagem responsiva, assegurando tratamento diferenciado e proporcional a serviços de natureza, risco e modelo de negócio distintos. (grifo meu)

Como fica claro pelo conteúdo da norma, devem ser levadas em consideração as desigualdades existentes entre os diferentes serviços. Como entre uma rede social de uma grande empresa multinacional e uma instância de uma rede social ainda de nicho, com público relativamente restrito e que, em geral, não busca resultado financeiro; e prevê ainda que a própria regulamentação pode causar assimetrias entre diferentes atores. Por esses motivos, deve ser assegurado o “tratamento diferenciado e proporcional”, mantendo assim uma proporção entre as plataformas e as sanções aplicadas a cada uma delas.

Reforçando essa ideia, prescreve o art. 39:

Art. 39. As obrigações previstas nos arts. 6º, 17, 18, 19, 20, 27, 28, 29, 31, 32 e 40 desta Lei aplicar-se-ão conforme as características e as funcionalidades do produto ou serviço de tecnologia da informação, moduladas de acordo com o grau de interferência do fornecedor do produto ou serviço sobre os conteúdos veiculados disponibilizados, o número de usuários e o porte do fornecedor. […] § 2º As obrigações referidas no caput deste artigo serão aplicadas de forma proporcional à capacidade do fornecedor de influenciar, de moderar ou de intervir na disponibilização, na circulação ou no alcance dos conteúdos acessíveis por crianças e adolescentes. § 3º A regulamentação definirá critérios objetivos para a aferição do grau de intervenção e para a aplicação proporcional das obrigações previstas neste artigo. (grifo meu)

Observa-se, novamente, a preocupação com a característica específica de cada tipo de serviço, suas funcionalidades e suas capacidades reais, além de seu porte, sendo as obrigações legais diretamente relacionadas às capacidades reais “do fornecedor” — ou do administrador da instância — de ingerência sobre os conteúdos compartilhados na rede.

Nesse sentido, a previsão do § 3º sobre a definição de critérios objetivos para essa avaliação é positiva para que possamos compreender efetivamente as medidas que deverão ser adotadas e como fazer a adequação das instâncias à regulamentação. Enquanto isso, aguardamos a promulgação da regulamentação específica.

Utilização por menores

O cerne do ECA Digital está na preocupação acerca do uso indevido das redes por menores, como disposto no art. 6º:

Art. 6º Os fornecedores de produtos ou serviços de tecnologia da informação direcionados a crianças e a adolescentes ou de acesso provável por eles deverão tomar medidas razoáveis desde a concepção e ao longo da operação de suas aplicações, com o objetivo de prevenir e mitigar riscos de acesso, exposição, recomendação ou facilitação de contato com os seguintes conteúdos, produtos ou práticas: I – exploração e abuso sexual; II – violência física, intimidação sistemática virtual e assédio; III – indução, incitação, instigação ou auxílio, por meio de instruções ou orientações, a práticas ou comportamentos que levem a danos à saúde física ou mental de crianças e de adolescentes, tais como violência física ou assédio psicológico a outras crianças e adolescentes, uso de substâncias que causem dependência química ou psicológica, autodiagnóstico e automedicação, automutilação e suicídio; IV – promoção e comercialização de jogos de azar, apostas de quota fixa, loterias, produtos de tabaco, bebidas alcoólicas, narcóticos ou produtos de comercialização proibida a crianças e a adolescentes; V – práticas publicitárias predatórias, injustas ou enganosas ou outras práticas conhecidas por acarretarem danos financeiros a crianças e a adolescentes; e VI – conteúdo pornográfico.

Também sendo previsto que:

Art. 8º Os fornecedores de produtos ou serviços de tecnologia da informação direcionados a crianças e a adolescentes ou de acesso provável por eles deverão: […] V - informar extensivamente a todos os usuários sobre a faixa etária indicada para o produto ou serviço no momento do acesso, conforme estabelecido pela política de classificação indicativa. (grifo meu)

Há ainda, no art. 12, I, a exigência de “medidas proporcionais, auditáveis e seguras” para verificação da idade ou faixa etária, com previsão de uma regulamentação posterior específica para os meios de verificação de idade e supervisão parental (§ 3º).

Enquanto a viabilidade de implementar alguma forma de verificação de idade permanece uma incógnita, especialmente na ausência da regulamentação específica a respeito, com base nesse trecho, especificamente no inciso V do art. 8º, é recomendável que as instâncias, tanto em sua página inicial quanto no processo de cadastro, informem de forma clara e objetiva que o uso da rede não é recomendado para menores de 18 anos — ou a idade que o administrador julgar mais conveniente. Essa atitude relativamente simples já pode desenquadrar a instância de algumas situações.

No caso, se não pudermos afirmar categoricamente que não se trata de serviço “de acesso provável” por crianças e adolescentes, minimamente estará excluído do rol dos serviços “direcionados a crianças e a adolescentes” e cumprirá a determinação legal de informar a faixa etária indicada para uso, demonstrando boa vontade, cooperação e boa-fé.

Supervisão parental

Havendo uso por menores, há previsões quanto à necessidade de implementação de ferramentas para a supervisão pelos responsáveis legais, sendo que deve novamente ser considerada, segundo o art. 17, I, “a tecnologia disponível e a natureza e o propósito do produto ou serviço” e, II, disponibilizadas informações para os responsáveis sobre as ferramentas existentes. Há, novamente, a pendência de uma regulamentação, também por parte da ANPD, sobre quais serão as diretrizes para os mecanismos de supervisão parental (art. 17, § 1º).

Ainda assim, em seu art. 18 é exigida a implementação de ferramentas que possibilitem aos responsáveis legais:

I – visualizar, configurar e gerenciar as opções de conta e privacidade da criança ou do adolescente; II – restringir compras e transações financeiras; III – identificar os perfis de adultos com os quais a criança ou o adolescente se comunica; IV – acessar métricas consolidadas do tempo total de uso do produto ou serviço; V – ativar ou desativar salvaguardas por meio de controles acessíveis e adequados; VI – dispor de informações e de opções de controle em língua portuguesa.

Bem como o art. 24, caput, estabelece que contas de menores de 16 anos devem estar vinculadas a um usuário ou conta do responsável legal.

Ressalte-se, porém, que todas essas determinações, as quais aparentam ser inviáveis atualmente, principalmente para instâncias pequenas, tornam-se desnecessárias para o caso de conseguirmos descaracterizar a instância como sendo “direcionada a crianças e a adolescentes ou de acesso provável por eles”, de forma a tornar todo o disposto no ECA Digital não aplicável. Mas isso apenas as determinações da ANPD e o desenrolar de casos futuros poderão determinar.

Cabe, no momento, apenas ressaltar, conforme art. 24, § 1º, I, e como destacado no tópico anterior, a inadequação do uso do serviço por menores de idade.

Art. 24. No âmbito de seus serviços, os provedores de produtos ou serviços direcionados a crianças e a adolescentes ou de acesso provável por eles deverão garantir que usuários ou contas de crianças e de adolescentes de até 16 (dezesseis) anos de idade estejam vinculados ao usuário ou à conta de um de seus responsáveis legais. § 1º Caso seus serviços sejam impróprios ou inadequados para crianças e adolescentes, os provedores de redes sociais deverão adotar medidas adequadas e proporcionais para: I – informar de maneira clara, destacada e acessível a todos os usuários que seus serviços não são apropriados; (grifo meu)

Casos de violações

Um ponto que acredito que possa ter causado desconforto em alguns administradores é o conteúdo do art. 27, principalmente seu § 2º, segundo os quais:

Art. 27. Os fornecedores de produtos ou serviços de tecnologia da informação disponíveis no território nacional deverão remover e comunicar os conteúdos de aparente exploração, de abuso sexual, de sequestro e de aliciamento detectados em seus produtos ou serviços, direta ou indiretamente, às autoridades nacionais e internacionais competentes, na forma de regulamento. […] § 2º Os fornecedores deverão reter, pelo prazo estabelecido no art. 15 da Lei nº 12.965, de 23 de abril de 2014 (Marco Civil da Internet), os seguintes dados associados a um relatório de conteúdo de exploração e de abuso sexual de criança ou de adolescente: I – conteúdo gerado, carregado ou compartilhado por qualquer usuário mencionado no relatório e metadados relacionados ao referido conteúdo; II – dados do usuário responsável pelo conteúdo e metadados a ele relacionados.

Tal retenção, além de incômoda, traz um potencial de aumento nos custos de manutenção dos servidor,es além da preocupação com possíveis sanções pelo seu descumprimento.

Contudo, ao analisar o referido art. 15 do Marco Civil da Internet, conclui-se ser um cenário não aplicável à maioria das instâncias, uma vez que não se tratam de pessoas jurídicas e de atividade profissional remunerada e com fins econômicos.

Art. 15. O provedor de aplicações de internet constituído na forma de pessoa jurídica e que exerça essa atividade de forma organizada, profissionalmente e com fins econômicos deverá manter os respectivos registros de acesso a aplicações de internet, sob sigilo, em ambiente controlado e de segurança, pelo prazo de 6 (seis) meses, nos termos do regulamento. (grifo meu)

Dessa forma, a retenção dos dados se torna desnecessária por parte da instância que receber a denúncia, devendo apenas tomar as ações de moderação cabíveis e notificar a autoridade competente. Excetuando-se apenas os casos de ordem judicial específica, a qual pode determinar a retenção de “registros relativos a fatos específicos em período determinado” (Art. 15, § 1º, Marco Civil da Internet).

Penalidades

O ECA Digital, como esperado para uma lei dessa magnitude, estabelece, em seu art. 35, caput e incisos, as penalidades a que estarão sujeitos os infratores de suas determinações, sendo elas

I – advertência, com prazo para adoção de medidas corretivas de até 30 (trinta) dias; II – multa simples, de até 10% (dez por cento) do faturamento do grupo econômico no Brasil no seu último exercício ou, ausente o faturamento, multa de R$ 10,00 (dez reais) até R$ 1.000,00 (mil reais) por usuário cadastrado do provedor sancionado, limitada, no total, a R$ 50.000.000,00 (cinquenta milhões de reais) por infração; (grifo meu)

Ressalte-se, novamente, a previsão de proporcionalidade e também da gradação na aplicação da penalidade.

Apesar de ser uma multa que pode atingir um valor considerável, uma vez que uma instância com 300 usuários já estaria sujeita a uma multa mínima de R$3.000 — valor esse que pode ser irrisório para grandes empresas, mas que com certeza faria grande diferença na manutenção da infraestrutura de uma instância —, é importante atentar-se ao restante dos parágrafos e incisos, especialmente o § 1º, incisos III e IV.

§ 1º Para fixação e gradação da sanção, deverão ser observadas, além da proporcionalidade e da razoabilidade, as seguintes circunstâncias: III – a capacidade econômica do infrator, no caso de aplicação da sanção de multa; IV – a finalidade social do fornecedor e o impacto sobre a coletividade no que se refere ao fluxo de informações no território nacional. (grifo meu)

A esse respeito, é apresentada, mais uma vez, a preocupação com a proporcionalidade e razoabilidade na aplicação das penalidades, além da capacidade econômica da instância e do seu administrador e a sua finalidade. Assim sendo, por mais que seja arriscado fazer prognósticos antecipados quanto à aplicação de uma nova lei, tudo leva a acreditar que, no caso em questão, a prioridade será pela aplicação de advertência, principalmente se for demonstrada cooperação e boa vontade por parte dos administradores.

Conclusões gerais

Acredito que o texto, além de longo, tenha sido um tanto maçante e não muito otimista para nossos queridos administradores. Gostaria de poder trazer mais respostas e soluções, mas não é algo possível neste momento. Então, nesta conclusão, tentarei resumir os principais ponto levantados, com as dúvidas, questionamentos e recomendações para o cenário atual, visando, principalmente, reduzir os riscos para as instâncias brasileiras.

Os principais pontos envolvem, basicamente, o que significa ser um serviço “direcionado a crianças e a adolescentes ou de acesso provável por eles”, se o fediverso pode ser considerado uma rede social de acordo com a definição da lei e a aplicação ou não do ECA Digital às instâncias, sendo que uma maior elucidação a esse respeito provavelmente resultaria na solução de muitos dos problemas levantados, como quanto à verificação da idade e a supervisão parental. Como destacado no restante do texto, porém, somente novas resoluções da ANPD e a jurisprudência poderão trazer tais respostas.

Todas as punições e sanções previstas foram acompanhadas de termos que estimulam o uso dos princípios de proporcionalidade e razoabilidade para a análise de cada caso, tornando improvável — porém não impossível — a aplicação de multas de valor muito expressivo. Sendo mais provável a aplicação inicial de advertências e progressão para multas em casos reincidentes.

Ainda assim, recomenda-se que as instâncias tomem alguns cuidados, especialmente com o objetivo de demonstrar ciência sobre a lei, boa-fé e boa vontade, fatores que podem influenciar na aplicação e gradação de sanções. Para isso, de forma simples:

  • Mantenham a atuação na moderação de conteúdos;
  • Adicionem avisos nas páginas inicial, Sobre e de cadastro que não se trata de um serviço destinado ou recomendado para menores de idade;
  • Demonstre disposição para colaborar com as autoridades em caso de notificação judicial ou extrajudicial.

Espero que o texto tenha sido informativo e ajude os administradores pelo menos a compreender melhor a situação atual de sua instância dentro da nova legislação.

Estou à disposição para perguntas ou contribuições em @vitu@bolha.us.

 
Leia mais...

from in.versos

Há em ti uma canção

Sem voz ou palavras

Uma canção de melodia terna

Cujas notas fazem vibrar meu coração

E a alma, animada, põe-se a bailar

Mas meus olhos, enamorados, esses se entregam

Entregam-se à doce melancolia de saber que não terão a companhia dos teus para verem o amanhecer

 
Leia mais...

from Riverfount

Saber dar bons nomes é uma das habilidades mais valiosas — e menos ensinadas — na engenharia de software. Em Python, nomes de variáveis e funções bem escolhidos tornam o código legível, reduzem ambiguidade e ajudam a preservar o design ao longo do tempo. Seguindo as diretrizes da PEP 8 e os princípios da Clean Architecture, este artigo mostra como criar nomes expressivos, consistentes e concisos, sem cair na armadilha dos identificadores longos ou genéricos. Você verá exemplos reais, más práticas comuns e um mini refactor que demonstra como nomes claros transformam o código.

1. Nomes são parte do design

Um código pode estar correto e, ainda assim, ser difícil de entender. Na maioria das vezes, o problema está nos nomes. Na Clean Architecture, os nomes devem refletir conceitos de negócio, não detalhes técnicos ou estruturais.

Má prática Boa prática Por quê?
db_user user_account Remove o detalhe técnico e foca no domínio.
json_response order_summary “JSON” é formato, não conceito.
user_data customer_profile “Data” é genérico; “profile” tem significado.

A lógica é simples: nomeie pelo propósito, não pela forma.

2. PEP 8: legibilidade é prioridade

A PEP 8 vai muito além da estética — ela é um guia de comunicação entre pessoas.
Algumas regras práticas:

  • Use snake_case para variáveis e funções.
  • Evite abreviações desnecessárias (cfg, cnt, ttl). Prefira nomes completos (config, count, total).
  • Use plural para coleções (users, orders) e singular para elementos únicos (user, order).
  • Remova redundâncias no contexto: dentro de UserService, prefira get_user() a get_user_data().
# ruim
def list_all_active_user_objects():
    ...

# bom
def list_active_users():
    ...

No segundo exemplo, o nome é simples e direto — o leitor entende a intenção de imediato.

3. Contexto é autoexplicativo

Bons nomes reduzem a necessidade de comentários. O código deve ser quase uma frase legível.

# ruim
data = get_data()

# bom
user_orders = order_service.fetch_recent_orders(user_id)

Outro exemplo comum:

# ruim
flag = True
if flag:
    process()

# bom
should_notify = True
if should_notify:
    send_notification()

Quando as variáveis comunicam intenção, o raciocínio flui naturalmente — o código se torna autoexplicativo.

4. Clareza e concisão

Nomes longos demais são tão ruins quanto nomes curtos e vagos.
O segredo é deixar o contexto carregar parte do significado.

Má prática Boa prática Justificativa
customer_account_balance_after_transaction_update new_balance O contexto já comunica o momento.
temporary_order_price_value temp_price Clareza mantida, sem prolixidade.
is_user_valid_and_authenticated is_authenticated Detalhes extras só atrapalham.

A clareza vem do contexto, não do tamanho do nome.

5. Nomear é projetar

Nomes são uma peça invisível da arquitetura do sistema. Quando todas as partes falam a mesma língua — a do negócio —, o código mantém coesão e resiliência. Trocar o banco ou o framework é fácil; perder clareza semântica, porém, é caro.

Bons nomes preservam a intenção arquitetural — mesmo após refatorações.
Eles são a ponte entre design técnico e linguagem de domínio.

6. Checklist rápido de boas práticas

  1. Use a linguagem do domínio, não da tecnologia.
  2. Seja claro, mas evite redundâncias.
  3. Adapte a granularidade: nomes locais curtos, nomes globais descritivos.
  4. Descreva propósito, não formato técnico.
  5. Evite genéricos (data, info, object).
  6. Mantenha consistência terminológica.
  7. Não exponha infraestrutura (db_, api_, json_) em camadas de domínio.
  8. Reveja nomes em PRs — eles comunicam tanto quanto o código em si.

7. Exemplo prático de refatoração

Um exemplo simples mostra o poder de nomes bem escolhidos.

Antes (difícil de entender):

def p(u, d):
    r = []
    for i in d:
        if i[1] == u:
            r.append(i[0])
    return r

Esse código até funciona, mas o leitor não sabe o que p, u, d ou r significam.

Depois (mesma lógica, nomes expressivos):

def get_orders_by_user(user_id: int, orders: list[tuple[int, int]]) -> list[int]:
    user_orders = []
    for order_id, owner_id in orders:
        if owner_id == user_id:
            user_orders.append(order_id)
    return user_orders

Sem mudar nada na lógica, o código agora se explica. Os nomes contam a história completa — o que está sendo filtrado, por quê e o que é retornado.

Conclusão

Dar bons nomes é mais do que estilo: é comunicação entre mentes técnicas. Variáveis bem nomeadas expressam intenção, reforçam arquitetura e tornam o código sustentável ao longo do tempo. O nome certo transforma a leitura em compreensão imediata — e isso é poder puro na engenharia de software.

Se este artigo te fez repensar como você nomeia variáveis, compartilhe com sua equipe ou continue a conversa no Mastodon: @riverfount@bolha.us

Espalhe boas práticas e ajude mais pessoas a escrever código que realmente se explica por si só.

 
Read more...

from in.versos

Sei que amas as flores com as quais teus tantos amantes te presenteiam. E talvez te entristeças por eu não te enviá-las.

Mas flores, querida, morrem cedo. Já o meu amor por ti jaz eternizado nos versos que te dediquei.

 
Leia mais...