Eu estive refletindo sobre os arquivos de configuração e sua relação com o código por um tempo e, dependendo do dia e da direção do vento, minhas opiniões parecem mudar. Cada vez mais, porém, continuo voltando à percepção que tive pela primeira vez ao aprender Lisp: há pouca diferença entre dados e código. Isso parece duplamente verdadeiro para arquivos de configuração. Quando visto sob a luz certa, um script Perl é pouco mais do que um arquivo de configuração para perl. Isso tende a ter consequências bastante pesadas para tarefas como controle de qualidade e divisões de trabalho, como quem deve ser responsável pela alteração dos arquivos de configuração.
O deslocamento do arquivo de configuração para a linguagem completa é geralmente lento e parece ser conduzido pelo desejo de ter um sistema genérico. A maioria dos projetos parecem começar pequenos, com alguns itens de configuração, como onde escrever logs, onde procurar dados, nomes de usuário e senhas, etc. Mas então eles começam a crescer: os recursos começam a ser ativados ou desativados, os tempos e a ordem das operações passam a ser controlados e, inevitavelmente, alguém quer começar a adicionar lógica a ele (por exemplo, use 10 se a máquina for X e 15 se a máquina for Y). Em um determinado ponto, o arquivo de configuração se torna um idioma específico de domínio, e mal escrito.
Agora que comecei a definir o cenário, aqui estão minhas perguntas:
- Qual é o verdadeiro propósito de um arquivo de configuração?
- Deve-se tentar manter os arquivos de configuração simples?
- Quem deve ser responsável por fazer alterações neles (desenvolvedores, usuários, administradores, etc.)?
- Eles devem ser controlados pela fonte (ver pergunta 3)?
Como eu disse antes, minhas respostas a essas perguntas mudam constantemente, mas agora estou pensando:
- para permitir que um não-programador altere grandes blocos de comportamento rapidamente
- sim, qualquer coisa que não seja granulada deve estar no código
- os usuários devem ser responsáveis pelos arquivos de configuração e os programadores devem ser responsáveis por uma camada de configuração entre os arquivos de configuração e o código que fornece um controle mais refinado do aplicativo
- não, mas a camada intermediária de granulação mais fina deve ser
fonte
Respostas:
Perguntas muito interessantes!
Eu tendo a limitar meus arquivos de configuração a um formato muito simples de "chave = valor", porque concordo totalmente com você que os arquivos de configuração podem rapidamente se tornar programas completos. Por exemplo, qualquer pessoa que já tentou "configurar" o OpenSER conhece a sensação de que você está falando: não é configuração, é programação (dolorosa).
Quando você precisa que seu aplicativo seja muito "configurável" de maneiras que você não pode imaginar hoje, o que você realmente precisa é de um sistema de plug - ins . Você precisa desenvolver seu aplicativo de forma que outra pessoa possa codificar um novo plug-in e conectá-lo ao seu aplicativo no futuro.
Então, para responder às suas perguntas:
Qual é o verdadeiro propósito de um arquivo de configuração?
Eu diria, para permitir que as pessoas que irão instalar seu aplicativo possam ajustar alguns parâmetros relacionados à implantação, como nome do host, número de threads, nomes dos plug-ins de que você precisa e os parâmetros de implantação para esses plug-ins (marque configuração do FreeRadius para um exemplo deste princípio), etc. Definitivamente não é o lugar para expressar a lógica de negócios.
Deve-se tentar manter os arquivos de configuração simples?
Definitivamente. Como você sugeriu, "programar" em um arquivo de configuração é horrível. Eu acredito que deve ser evitado.
Quem deve ser responsável por fazer alterações neles (desenvolvedores, usuários, administradores, etc.)?
Em geral, eu diria administradores, que implantam o aplicativo.
Eles devem ser controlados pela fonte (ver pergunta 3)?
Normalmente não faço o controle de origem dos arquivos de configuração, mas faço o controle de origem de um arquivo de configuração de modelo, com todos os parâmetros e seus valores padrão e comentários que descrevem o que eles fazem. Por exemplo, se um arquivo de configuração é nomeado
database.conf
, eu geralmente controlo a origem de um arquivo chamadodatabase.conf.template
. Agora é claro que estou falando sobre o que faço como desenvolvedor . Como administrador , posso querer controlar a origem das configurações reais que escolhi para cada instalação. Por exemplo, gerenciamos algumas centenas de servidores remotamente e precisamos manter o controle de suas configurações: optamos por fazer isso com o controle de origem.Editar: Embora eu acredite que o acima seja verdadeiro para a maioria das aplicações, sempre há exceções, é claro. Seu aplicativo pode permitir que seus usuários configurem regras complexas dinamicamente, por exemplo. A maioria dos clientes de email permite que os usuários definam regras para o gerenciamento de seus emails (por exemplo, "todos os emails vindos de 'john doe' e que não me tenham no campo Para: devem ser descartados"). Outro exemplo é um aplicativo que permite ao usuário definir uma nova oferta comercial complexa. Você também pode pensar em aplicativos como o Cognos, que permitem que seus usuários criem relatórios de banco de dados complexos. O cliente de e-mail provavelmente oferecerá ao usuário uma interface simples para definir as regras, e isso irá gerar um arquivo de configuração complexo (ou talvez até mesmo um pouco de código). Por outro lado, a configuração definida pelo usuário para as ofertas comerciais pode ser salva em um banco de dados, de forma estruturada (nem uma estrutura chave = valor simples nem uma parte do código). E alguns outros aplicativos podem até permitir que o usuário codifique em python ou VB, ou alguma outra linguagem com capacidade de automação. Em outras palavras ... sua milhagem pode variar.
fonte
Está bem. Você terá alguns usuários que querem uma configuração realmente simples, você deve fornecê-la a eles. Ao mesmo tempo, você terá solicitações constantes de "Você pode adicionar isso? Como faço no arquivo de configuração?", Não vejo por que você não pode oferecer suporte a ambos os grupos.
O projeto no qual estou trabalhando atualmente usa Lua para seu arquivo de configuração. Lua é uma linguagem de script e funciona muito bem neste cenário. Está disponível um exemplo de nossa configuração padrão .
Você notará que são principalmente instruções key = value, em que value pode ser qualquer um dos tipos embutidos de Lua. A coisa mais complicada que existem são listas, e elas não são realmente complicadas (é apenas uma questão de sintaxe).
Agora estou apenas esperando que alguém pergunte como definir a porta de seu servidor para um valor aleatório toda vez que ele for inicializado ...
fonte
Recentemente, eu estava trabalhando em um projeto e percebi que queria ter condicionais dentro do meu arquivo de configuração - que anteriormente era apenas um muito simples no formato:
Não queria escrever uma minilinguagem porque, a menos que o fizesse com muito cuidado, não poderia permitir a flexibilidade que seria útil.
Em vez disso, decidi que teria dois formulários:
Se o arquivo começar com "#!" e fosse executável, analisaria o resultado de sua execução.
Caso contrário, eu o leria como está
Isso significa que agora posso permitir que as pessoas escrevam "arquivos de configuração" semelhantes a este:
Assim, consigo o poder de um arquivo de configuração dinâmica se o usuário quiser usá-lo, e a simplicidade de não ter que escrever minha própria minilinguagem.
fonte
Todo esquema de arquivo de configuração (de duração suficiente) eventualmente se torna uma linguagem de programação. Devido a todas as implicações que você descreve, é sábio para o designer do arquivo de configuração perceber que está criando uma linguagem de programação e planejar de acordo, para não sobrecarregar os futuros usuários com legado ruim.
fonte
Tenho uma filosofia diferente sobre os arquivos de configuração. Os dados sobre como um aplicativo deve ser executado ainda são dados e, portanto, pertencem a um armazenamento de dados, não ao código (um arquivo de configuração IMO é código). Se os usuários finais precisarem alterar os dados, o aplicativo deve fornecer uma interface para fazer isso.
Eu só uso arquivos de configuração para apontar para armazenamentos de dados.
fonte
Você poderia recorrer à teoria da computação para definir o que conta como uma linguagem de programação. Se o formato do seu arquivo de configuração for Turing Complete, então ele conta razoavelmente como uma linguagem de programação. Por esta definição, um formato de arquivo para descrever os níveis de Sokoban conta como uma linguagem de programação (veja aqui ). Existem outros níveis de complexidade abaixo do Turing Complete que também podem contar, como Gramáticas regulares e Autômatos de pushdown .
Outra maneira de ver isso é que muitos arquivos de configuração são capazes apenas de marcação de dados, enquanto uma linguagem de programação adequada deve ser capaz de implementar algoritmos . Por exemplo, JSON é um formato de arquivo de configuração, enquanto ECMA Script é uma linguagem de programação.
fonte
Aqui está minha opinião:
Para permitir que o comportamento de tempo de execução de um aplicativo seja modificado facilmente. Isso pode ser feito por programadores ou não programadores, dependendo das necessidades. Isso pode ser durante o desenvolvimento, mas frequentemente vejo os arquivos de configuração como uma forma de ajudar a tornar um programa mais flexível em qualquer ponto.
Sim. Acho que os arquivos de configuração devem ser o mais simples possível, dada a restrição de que você pode precisar de várias opções para controlar diferentes comportamentos do seu tempo de execução. Eu prefiro agrupar as definições de configuração e simplificá-las o máximo possível.
Depende do que e por que a mudança está sendo feita. Se os usuários vão alterá-lo, um front-end deve ser feito para ocultá-los dos detalhes. O mesmo costuma acontecer com os não desenvolvedores em geral.
Costumo controlar a configuração "padrão" de origem, mas tenho uma maneira de substituir isso por sistema para o tempo de execução real.
Quanto a adicionar lógica ao arquivo de configuração - eu evitaria isso. Eu acho que é melhor apenas ter o arquivo de configuração alternando a lógica em seu aplicativo. O comportamento em arquivos de configuração leva à falta de capacidade de manutenção e compreensão, na minha experiência. Eu prefiro manter os arquivos de configuração o mais simples possível.
fonte
Eu tendo a concordar com a premissa desta questão. Eu evito me meter em problemas prevendo logo que isso vai acontecer e, portanto, nunca rolo meu próprio sistema de configuração.
E resignar-me a viver com qualquer decisão que tomei, ou se não puder, refatorar para usar uma das escolhas acima que melhor se adapte à aplicação.
O que quero dizer é que não há realmente nenhuma razão para usar uma solução de configuração desenvolvida internamente. Por um lado, é mais difícil para seus usuários aprender um novo formato de configuração específico do aplicativo. Por outro lado, você se beneficia de todas as várias correções de bugs e atualizações que vêm gratuitamente ao usar uma solução pronta para uso. Finalmente, o deslocamento de recursos é colocado de lado, porque, bem, você não pode simplesmente adicionar mais um recurso sem realmente fazer uma grande revisão, porque o sistema de configuração não está realmente em suas mãos em primeiro lugar.
fonte
Depende do que você concorda com outros desenvolvedores da equipe. Você está usando arquivos de configuração apenas como arquivos de configuração ou está criando um aplicativo Model Driven .
Sintomas de o arquivo de configuração se tornar uma linguagem de programação:
fonte
Os arquivos de configuração invariavelmente avançam lentamente para se tornarem "linguagens de programação totalmente desenvolvidas" feias e ilógicas. É preciso arte e habilidade para projetar boas linguagens de programação, e as linguagens de configuração transformadas em linguagem de programação tendem a ser horrendas.
Uma boa abordagem é usar uma linguagem bem projetada, como python ou ruby, e usá-la para criar uma DSL para sua configuração. Dessa forma, sua linguagem de configuração pode permanecer simples na superfície, mas na verdade é a linguagem de programação completa.
fonte
Acredito que sua pergunta seja muito relevante dada a mudança para "interfaces fluentes". Muitos desenvolvedores "viram a luz" em relação aos aplicativos configurados em XML. Usar XML pode ser muito detalhado e difícil de editar corretamente (especialmente se nenhum esquema for fornecido). Ter uma interface fluente permite que o desenvolvedor configure o aplicativo em um idioma específico de domínio com a ajuda de alguns pares de valores-chave de um arquivo de configuração de texto simples (ou talvez parâmetros de linha de comando). Também torna muito fácil instalar e configurar novas instâncias do aplicativo para teste ou qualquer outra coisa.
Aqui estão minhas respostas à sua pergunta:
Um arquivo de configuração é uma forma de permitir ao usuário personalizar o comportamento de seu programa em tempo de execução.
Idealmente, eu pensaria que os arquivos de configuração deveriam pelo menos ser complementados por uma interface fluente para configurar o programa (isso é útil em muitos aspectos). Se você precisar de um arquivo de configuração, ele deve ser mantido muito simples, nada além de pares de valor-chave.
Acho que a resposta para isso depende da sua organização. Deve ser responsabilidade da pessoa que está implantando o software garantir que ele esteja configurado corretamente.
Vou roubar essa resposta de outra pessoa :) Gosto da ideia de armazenar uma configuração de modelo no controle de origem e modificá-la para as necessidades de cada usuário local. Provavelmente, o arquivo de configuração de um desenvolvedor é o pesadelo de outro desenvolvedor, então é melhor deixar coisas que variam de acordo com o usuário fora do controle de origem. Ter um modelo também é uma boa maneira de permitir que a pessoa que está implantando o aplicativo (ou outros desenvolvedores) veja exatamente quais valores são válidos para o arquivo de configuração.
fonte
Tenho visto programas python em que o arquivo de configuração é código. Se você não precisa fazer nada especial (condicionais, etc.), não é muito diferente de outros estilos de configuração. por exemplo, eu poderia fazer um arquivo
config.py
com coisas como:e o único fardo para o usuário, em comparação com (digamos) arquivos INI, é que eles precisam colocar '' em torno das strings. Sem dúvida, você poderia fazer a mesma coisa em outras línguas interpretadas. Ele oferece capacidade ilimitada de complicar seu arquivo de configuração, se necessário, com o risco de assustar seus usuários.
fonte
Sim, os arquivos de configuração devem ser simples. Eles não devem conter nenhuma 'lógica' - pense neles como uma lista de expressões em declarações if, não as declarações condicionais em sua totalidade.
Eles estão lá para permitir que o usuário decida qual das opções codificadas dentro do aplicativo deve ser usada, então não tente complicá-los, isso vai acabar sendo contraproducente - você pode acabar escrevendo arquivos de configuração simples para controlar como o arquivo de configuração original deve ser configurado de outra forma!
fonte
Um dos objetivos do trabalho "Oslo" na Microsoft é permitir (embora não exigir) a resolução desse problema.
Isso significa que o equivalente aos arquivos de configuração de hoje pode ser rico o suficiente para suportar a edição textual e gráfica de sua configuração. A ferramenta gráfica será fornecida com "Oslo" (codinome "Quadrant").
fonte
Serei o contrário e apresentarei que é apenas uma linguagem quando incorpora mais do que pode ser representado por XML; ou então quando XML é considerado uma linguagem.
Como alternativa, a maioria dos arquivos de configuração podem ser considerados classes, mas com apenas propriedades e nenhum método. E sem métodos, não acho que seja uma linguagem.
Em última análise, "linguagem" é uma abstração mole, mas sim, as bordas são ambíguas.
fonte
O código das nossas aplicações torna-se menos importante ... Existe o scripting, existem todos os tipos de atributos que definem o comportamento das classes, métodos, argumentos dos métodos e propriedades. Os usuários podem definir gatilhos e restrições de banco de dados. Pode haver arquivos de configuração muito complicados. Às vezes, o usuário pode definir folhas de estilo XSLT para manipular a entrada e a saída porque nossos sistemas precisam estar abertos (SOA). E há coisas como o BizzTalk que também precisam de configuração complexa. Os usuários podem definir fluxos de trabalho complexos.
Temos que escrever um código melhor para lidar com este ambiente complexo, então o código de nossas aplicações se torna mais importante ...
fonte
Sou um grande fã de usar programas python como arquivos de configuração, especialmente para daemons. Eu gosto de deixar o daemon completamente vazio de configuração, exceto para a "porta de configuração". O programa python então se conecta ao daemon e prossegue para criar objetos no daemon e conectá-los para criar a configuração desejada. Depois que tudo estiver configurado, o daemon pode ser deixado para funcionar sozinho. Os benefícios, é claro, são que você obtém uma linguagem de programação completa para escrever seus arquivos de configuração e, como você já tem uma maneira de falar com o daemon de outro programa, pode usá-la para depurar e obter estatísticas. A principal desvantagem é ter que lidar com mensagens de outro programa chegando a qualquer momento.
fonte
Arquivo de configuração : "Qual é o meu propósito?"
Você : "Configure a manteiga."
Arquivo de configuração : "Ok ..."
Arquivo de configuração : "Qual é o meu propósito?"
Você : "Você configura a manteiga."
Arquivo de configuração : "Meu Deus."
Não existe um "propósito verdadeiro" para um arquivo de configuração. É tudo o que faz sentido para a sua aplicação. Em geral, coisas que diferem (ou podem diferir) entre as máquinas e não mudam no meio da execução do aplicativo provavelmente devem estar em um arquivo de configuração. Padrões, portas e endereços para outros serviços são ótimos candidatos. Chaves e segredos também são ótimos candidatos, mas devem ser tratados separadamente de sua configuração normal por motivos de segurança. Eu discordo que o propósito de um arquivo de configuração é permitir que mudanças rápidas sejam feitas. O objetivo deve ser permitir flexibilidade na configuração de seu aplicativo. Se um arquivo de configuração é uma maneira rápida e fácil de permitir essa flexibilidade, melhor ainda - mas você não deve querer que seus arquivos de configuração sejam alterados com frequência.
Sim e não. Você deve tentar tornar o código do seu aplicativo simples? Sim. Você deve tentar tornar tudo o que escreve simples e direto ao ponto. Não é mais complicado do que precisa ser. O mesmo se aplica à sua configuração. No entanto, isso é muito específico do aplicativo. Codificar o que deveria estar na configuração porque tornaria sua configuração "muito complicada" é um projeto ruim. Na verdade, tentar "manter as coisas simples" é o motivo pelo qual os arquivos de configuração acabam sendo uma bagunça gigante. Às vezes, o movimento mais simples é modularizar. É por isso que seus arquivos de configuração devem ser escritos em uma linguagem de programação de propósito geral bem conhecida - não em uma linguagem de configuração terrível (leia: todas as "linguagens de configuração" são uma porcaria ).
Novamente, quem deve modificar os arquivos de configuração depende totalmente do aplicativo. Mas eu concordo com o miniquark, quem está implantando o aplicativo fica encarregado da configuração.
Controle de origem tudo o que você puder. O controle da fonte é ótimo. Você pode reverter coisas com muita facilidade e tem um histórico completo das alterações feitas e um registro de quem as fez. Então por que não?
fonte