ConstructiCat Logo
CodeBust.
Browse section ▾

Codificação rígida (hard coding).

Inserir dados no código-fonte de um programa

A codificação rígida (hard coding) é a prática de desenvolvimento de software que consiste em embutir dados diretamente no código-fonte de um programa ou de outro objeto executável, em vez de obter os dados de fontes externas ou gerá-los em tempo de execução.

Dados codificados de forma rígida normalmente só podem ser modificados editando o código-fonte e recompilando o executável, embora possam ser alterados na memória ou em disco usando um depurador ou um editor hexadecimal.

Dados codificados de forma rígida são mais adequados para informações que não mudam, como constantes físicas, números de versão e elementos de texto estáticos.

Dados codificados de forma flexível (soft coding), por outro lado, codificam informações arbitrárias por meio de entrada do usuário, arquivos de texto, arquivos INI, respostas de servidores HTTP, arquivos de configuração, macros de pré-processador, constantes externas, bancos de dados, argumentos de linha de comando, e são determinados em tempo de execução.

Visão geral

A codificação rígida exige que o código-fonte do programa seja alterado sempre que os dados de entrada ou o formato desejado mudam, quando poderia ser mais conveniente para o usuário final alterar esse detalhe por algum meio externo ao programa.

A codificação rígida muitas vezes é necessária, mas também pode ser considerada um antipadrão. Os programadores podem não ter elaborado uma solução de interface de usuário dinâmica para o usuário final, mas ainda assim precisam entregar o recurso ou lançar o programa. Isso costuma ser temporário, mas resolve, no curto prazo, a pressão para entregar o código. Mais tarde, a codificação flexível é feita para permitir que um usuário forneça parâmetros que deem ao usuário final uma forma de modificar os resultados ou o desfecho.

O termo "hard-coded" (codificado de forma rígida) foi inicialmente usado como uma analogia à fiação direta de circuitos e pretendia transmitir a inflexibilidade que resulta de seu uso no projeto e na implementação de software. No contexto de ambientes colaborativos de desenvolvimento extensíveis em tempo de execução, como os MUDs, a codificação rígida também se refere a desenvolver o núcleo do sistema, responsável por tarefas de baixo nível e pela execução de scripts, em oposição à codificação flexível, que consiste em desenvolver os scripts de alto nível interpretados pelo sistema em tempo de execução, com valores de fontes externas, como arquivos de texto, arquivos INI, macros de pré-processador, constantes externas, bancos de dados, argumentos de linha de comando, respostas de servidores HTTP, arquivos de configuração e entrada do usuário. Nesse caso, o termo não é pejorativo e se refere ao desenvolvimento em geral, em vez de especificamente embutir dados de saída.

Backdoors

Codificar credenciais de forma rígida é uma maneira comum de criar uma backdoor. Credenciais codificadas de forma rígida normalmente não são visíveis em arquivos de configuração nem na saída de comandos de enumeração de contas e não podem ser facilmente alteradas ou contornadas pelos usuários. Se descoberta, um usuário pode conseguir desativar essa backdoor modificando e recompilando o programa a partir de seu código-fonte (se o código estiver disponível publicamente), descompilando ou fazendo engenharia reversa do software, editando diretamente o código binário do programa ou instituindo uma verificação de integridade (como assinaturas digitais, proteção contra adulteração e anti-trapaça) para impedir o acesso inesperado, mas tais ações costumam ser proibidas por um contrato de licença de usuário final.

Gestão de direitos digitais

Como medida de gestão de direitos digitais (DRM), os desenvolvedores de software podem codificar de forma rígida um número de série exclusivo diretamente em um programa. Ou é comum codificar de forma rígida uma chave pública, criando um DRM para o qual é inviável criar um keygen.

No caso oposto, um cracker de software pode codificar de forma rígida um número de série válido no programa ou até impedir que o executável o solicite ao usuário, permitindo que cópias não autorizadas sejam redistribuídas sem a necessidade de inserir um número válido, compartilhando assim a mesma chave para cada cópia, caso uma tenha sido codificada de forma rígida.

Caminho de instalação fixo

Se um programa Windows é programado para presumir que está sempre instalado em C:\Program Files\Appname e alguém tenta instalá-lo em uma unidade diferente por motivos de espaço ou organização, ele pode falhar ao instalar ou ao executar após a instalação. Esse problema pode não ser identificado no processo de testes, já que o usuário comum instala na unidade e no diretório padrão, e os testes podem não incluir a opção de alterar o diretório de instalação. No entanto, é aconselhável que programadores e desenvolvedores não fixem o caminho de instalação de um programa, pois o caminho de instalação padrão depende do sistema operacional, da versão do SO e das decisões do administrador de sistemas. Por exemplo, muitas instalações do Microsoft Windows usam a unidade C: como seu disco rígido principal, mas isso não é garantido.

Houve um problema semelhante com os microprocessadores dos primeiros computadores, que iniciavam a execução em um endereço fixo na memória.

Disco de inicialização

Alguns programas "protegidos contra cópia" procuram um arquivo específico em um disquete ou pen drive na inicialização para verificar se não são cópias não autorizadas. Se o computador for substituído por uma máquina mais nova, que não tem unidade de disquete, o programa que a exige não pode mais ser executado, já que o disquete não pode ser inserido.

Este último exemplo mostra por que a codificação rígida pode acabar sendo impraticável mesmo quando parece, no momento, que funcionaria perfeitamente. Nas décadas de 1980 e 1990, a grande maioria dos PCs vinha equipada com pelo menos uma unidade de disquete, mas as unidades de disquete caíram em desuso posteriormente. Um programa codificado dessa forma 15 anos atrás poderia enfrentar problemas se não fosse atualizado.

Pastas especiais

Alguns sistemas operacionais Windows têm as chamadas pastas especiais, que organizam os arquivos de forma lógica no disco rígido. Há problemas que podem surgir envolvendo a codificação rígida:

Caminho do perfil

Alguns programas Windows codificam de forma rígida o caminho do perfil para locais definidos pelo desenvolvedor, como C:\Documents and Settings\Username. Esse é o caminho para a grande maioria do Windows 2000 ou superior, mas causaria um erro se o perfil estivesse armazenado em uma rede ou realocado de outra forma. A maneira correta de obtê-lo é chamar a função GetUserProfileDirectory ou resolver a variável de ambiente %userprofile%. Outra suposição que os desenvolvedores costumam fazer é que o perfil está localizado em um disco rígido local.

Caminho da pasta Meus Documentos

Alguns programas Windows codificam de forma rígida o caminho para My Documents como ProfilePath\My Documents. Esses programas funcionariam em máquinas que rodam a versão em inglês, mas em versões localizadas do Windows essa pasta normalmente tem um nome diferente. Por exemplo, nas versões em italiano a pasta My Documents chama-se Documenti. My Documents também pode ter sido realocada usando o Redirecionamento de Pasta na Diretiva de Grupo no Windows 2000 ou superior. A maneira adequada de obtê-lo é chamar a função SHGetFolderPath.

Solução

Uma referência indireta, como uma variável dentro do programa chamada "FileName", poderia ser expandida acessando uma janela de diálogo de "selecionar arquivo", e o código do programa não precisaria ser alterado se o arquivo fosse movido.

A codificação rígida é especialmente problemática ao preparar o software para tradução para outras línguas.

Em muitos casos, um único valor codificado de forma rígida, como o tamanho de um vetor, pode aparecer várias vezes no código-fonte de um programa. Isso seria um número mágico. Isso costuma causar um bug no programa se algumas das ocorrências do valor forem modificadas, mas não todas. Esse tipo de bug é difícil de encontrar e pode permanecer no programa por muito tempo. Um problema semelhante pode ocorrer se o mesmo valor codificado de forma rígida for usado para mais de um valor de parâmetro, por exemplo, um vetor de 6 elementos e um comprimento mínimo de cadeia de entrada de 6. Um programador pode, por engano, alterar todas as instâncias do valor (muitas vezes usando o recurso de localizar e substituir de um editor) sem verificar no código como cada instância é usada. Ambas as situações são evitadas definindo constantes, que associam nomes aos valores, e usando os nomes das constantes para cada ocorrência no código.

Um caso importante de codificação rígida é quando cadeias de caracteres são colocadas diretamente no arquivo, o que obriga os tradutores a editar o código-fonte para traduzir um programa. (Existe uma ferramenta chamada gettext que permite deixar as cadeias de caracteres nos arquivos, mas deixa os tradutores traduzi-las sem alterar o código-fonte; ela efetivamente remove a codificação rígida das cadeias.)

Competições de programação

Em competições de programação como a Olimpíada Internacional de Informática, os participantes precisam escrever um programa com um padrão específico de entrada e saída de acordo com o que as questões exigem.

Nos raros casos em que o número possível de entradas é pequeno o suficiente, um participante pode considerar usar uma abordagem que mapeia todas as entradas possíveis para suas saídas corretas. Esse programa seria considerado uma solução codificada de forma rígida, em oposição a uma solução algorítmica (ainda que o programa codificado de forma rígida possa ser a saída de um programa algorítmico).

Codificação flexível (soft coding)

A codificação flexível (soft coding) é um termo de programação que se refere a obter um valor ou função de algum recurso externo, como arquivos de texto, arquivos INI, macros de pré-processador, constantes externas, arquivos de configuração, argumentos de linha de comando, bancos de dados, entrada do usuário e respostas de servidores HTTP. É o oposto da codificação rígida, que se refere a codificar valores e funções no código-fonte.

Prática de programação

Evitar a codificação rígida de valores que costumam ser alterados é uma boa prática de programação. Os usuários do software devem poder personalizá-lo conforme suas necessidades, dentro do razoável, sem precisar editar o código-fonte do programa. Da mesma forma, programadores cuidadosos evitam números mágicos em seu código para melhorar sua legibilidade e facilitar a manutenção. Essas práticas geralmente não são chamadas de codificação flexível.

O termo é geralmente usado quando a codificação flexível se torna um antipadrão. Abstrair valores e recursos em excesso pode introduzir mais complexidade e problemas de manutenção do que se teria ao alterar o código quando necessário. A codificação flexível, nesse sentido, foi destaque em um artigo no The Daily WTF.

Problemas potenciais

No extremo, programas com codificação flexível desenvolvem suas próprias linguagens de script mal projetadas e implementadas, além de arquivos de configuração que exigem habilidades avançadas de programação para serem editados. Isso pode levar à produção de utilitários para auxiliar na configuração do programa original, e esses utilitários muitas vezes acabam eles próprios usando codificação flexível.

A fronteira entre a configurabilidade adequada e a codificação flexível problemática muda conforme o estilo e a natureza de um programa. Programas de código fechado precisam ser muito configuráveis, pois o usuário final não tem acesso ao código para fazer qualquer alteração. Software interno e software com distribuição limitada podem ser menos configuráveis, pois distribuir cópias alteradas é mais simples. Aplicações web feitas sob medida costumam ser melhores com configurabilidade limitada, pois alterar os scripts raramente é mais difícil do que alterar um arquivo de configuração.

Para evitar a codificação flexível, considere o valor para o usuário final de qualquer flexibilidade adicional que você ofereça e compare-o com o aumento de complexidade e os custos contínuos de manutenção relacionados que a configurabilidade adicionada envolve.

Alcançando flexibilidade

Existem vários padrões de projeto legítimos para alcançar a flexibilidade que a codificação flexível tenta proporcionar. Uma aplicação que exige mais flexibilidade do que é apropriado para um arquivo de configuração pode se beneficiar da incorporação de uma linguagem de script. Em muitos casos, o projeto apropriado é uma linguagem específica de domínio integrada a uma linguagem de script estabelecida. Outra abordagem é mover a maior parte da funcionalidade de uma aplicação para uma biblioteca, fornecendo uma API para escrever rapidamente aplicações relacionadas.