Por favor, leia a pergunta com atenção: ela pergunta como , não por quê .
Recentemente, deparei com esta resposta , que sugere o uso de um banco de dados para armazenar dados imutáveis:
Parece que muitos dos números mágicos que você descreve - principalmente se dependem de parte - são realmente dados, não código. [...] Pode significar um banco de dados do tipo SQL ou simplesmente um arquivo de texto formatado.
Parece-me que, se você tem dados que fazem parte do que o seu programa faz, então a coisa a fazer é colocá-los no programa . Por exemplo, se a função do seu programa é contar vogais, o que há de errado em ter vowels = "aeiou"
nela? Afinal, a maioria das linguagens possui estruturas de dados projetadas exatamente para esse uso. Por que você se incomodaria em separar os dados colocando-os em um "arquivo de texto formatado", conforme sugerido acima? Por que não apenas tornar esse arquivo de texto formatado na sua linguagem de programação preferida? Agora é um banco de dados? Ou é código?
Tenho certeza que alguns vão pensar que esta é uma pergunta idiota, mas eu pergunto com toda a seriedade. Eu sinto que "código e dados separados" estão emergindo culturalmente como algum tipo de verdade auto-evidente, junto com outras coisas óbvias, como "não dê nomes enganosos às suas variáveis" e "não evite usar espaços em branco apenas porque sua linguagem considera insignificante ".
Tomemos, por exemplo, este artigo: O problema com a separação de dados do código fantoche . O problema ? Que problema? Se o Puppet é uma linguagem para descrever minha infraestrutura, por que não pode também descrever que o servidor de nomes é 8.8.8.8? Parece-me que o problema não é que códigos e dados sejam misturados, 1 mas que o Puppet carece de estruturas de dados suficientemente ricas e de maneiras de interagir com outras coisas.
Acho essa mudança perturbadora. A programação orientada a objetos disse "queremos estruturas de dados arbitrariamente ricas" e, portanto, dotou as estruturas de dados com poderes de código. Você obtém o encapsulamento e a abstração como resultado. Até os bancos de dados SQL possuem procedimentos armazenados. Quando você sequestra dados em YAML ou arquivos de texto ou bancos de dados burros, como se estivesse removendo um tumor do código, perde tudo isso.
Alguém pode explicar como surgiu essa prática de separar dados de código e para onde está indo? Alguém pode citar publicações de luminares ou fornecer alguns dados relevantes que demonstrem "código separado dos dados" como um mandamento emergente e ilustrem sua origem?
1: se alguém pode fazer essas distinções. Estou olhando para você, programadores Lisp.
fonte
Respostas:
Existem muitas boas razões para separar os dados do código e outras não. A seguir, lembre-se.
Oportunidade. Quando o valor dos dados é conhecido? É no momento em que o código é gravado, quando é compilado, vinculado, liberado, licenciado, configurado, iniciado ou em execução. Por exemplo, o número de dias em uma semana (7) é conhecido com antecedência, mas a taxa de câmbio USD / AUD será conhecida com atraso.
Estrutura. Esse é um período único de dados definido de acordo com uma única consideração ou pode ser herdado ou parte de uma coleção maior de itens? Idiomas como YAML e JSON permitem a combinação de valor de várias fontes. Talvez algumas coisas que inicialmente pareçam imutáveis sejam melhor acessadas como propriedades em um gerenciador de configuração.
Localidade. Se todos os itens de dados estiverem armazenados em um número limitado de locais, será muito mais fácil gerenciá-los, principalmente se alguns precisarem ser alterados para novos valores (imutáveis). A edição do código-fonte apenas para alterar os valores dos dados apresenta o risco de alterações e bugs inadvertidos.
Separação de preocupações. Para que os algoritmos funcionem corretamente, é melhor separar a consideração de quais valores de dados usar. Os dados são necessários para testar algoritmos, não para fazer parte deles. Consulte também http://c2.com/cgi/wiki?ZeroOneInfinityRule .
Em resposta à sua pergunta, isso não é algo novo. Os princípios básicos não mudaram em mais de 30 anos e foram escritos repetidamente sobre esse período. Não me lembro de nenhuma publicação importante sobre o assunto, pois geralmente não é considerado controverso, apenas algo para explicar aos recém-chegados. Há um pouco mais aqui: http://c2.com/cgi/wiki?SeparationOfDataAndCode .
Minha experiência pessoal é que a importância dessa separação em um pedaço específico de software se torna maior ao longo do tempo, e não menos. Os valores codificados são movidos para os arquivos de cabeçalho, os valores compilados são movidos para os arquivos de configuração, e os valores simples tornam-se parte de estruturas hierárquicas e gerenciadas.
Quanto às tendências, não vi grandes mudanças de atitude entre programadores profissionais (mais de 10 anos), mas o setor está cada vez mais cheio de jovens e muitas coisas que eu pensava serem conhecidas e decididas a continuar sendo desafiadas e reinventadas, às vezes fora de moda. idéias, mas às vezes por ignorância.
fonte
Locality
também funciona de maneira inversa: acabamos com um tipo de sistema do tipo plug-in devido a requisitos personalizados para diferentes clientes e, após vários anos de tentativa e erro, aprendemos a manter suas constantes (até tabelas, por meio de listas de dictos) fora do banco de dados e no código. Tanto porque usá-lo em qualquer lugar que não seja esse "plug-in" está incorreto e porque as alterações são versionadas automaticamente quando ocorrem alterações.Os dados são dimensionados muito melhor e podem ser consultados e modificados com muito mais facilidade, quando separados do código. Mesmo que seus dados sejam de natureza codificada - por exemplo, seus dados representam regras ou comandos - se você pode armazenar representá-lo como dados estruturados, poderá aproveitar os benefícios de armazenar separadamente:
permissões
Se os dados estiverem codificados, você precisará editar o arquivo de origem para editar esses dados. Isso significa que:
Somente desenvolvedores podem editar dados. Isso é ruim - a entrada de dados não é algo que requer as habilidades e o conhecimento do desenvolvedor.
Não desenvolvedores podem editar o arquivo de origem. Isso é ruim - eles podem danificar o arquivo de origem sem nem mesmo saber!
Os dados são codificados em arquivos de origem separados, e os não desenvolvedores têm acesso apenas a esses arquivos. Mas isso realmente não conta - agora os dados são separados do código e armazenados em seus próprios arquivos ...
edição
Portanto, sobre quem pode editar os dados, é melhor armazená-los separadamente. Que tal como eles editarão os dados? Se você tem muitos dados, digitá-los manualmente é entediante e elimina erros. Ter alguma interface para isso é muito melhor! Mesmo que você ainda precise digitar tudo, não precisará digitar a placa do formato, portanto há menos chances de você estragar o formato e estragar o arquivo inteiro!
Se os dados estiverem codificados, a criação dessa interface significa que uma ferramenta automatizada editará os arquivos de origem manuscritos. Deixe isso acontecer - uma ferramenta automatizada abrirá seus arquivos de origem, tentará descobrir onde os dados devem estar e modificar esse código. Brrr ... A Microsoft introduziu classes parciais no C # apenas para evitar essas coisas ...
Se os dados estiverem separados, sua ferramenta automatizada precisará apenas editar arquivos de dados. Prefiro acreditar que programas de computador editando arquivos de dados não são tão incomuns hoje em dia ...
escala
O código e os dados são dimensionados de maneira muito diferente. À medida que seu código cresce, você deseja separá-lo em mais classes e métodos (ou estruturas e funções de dados), mas seus dados - não importa quanto cresça - você deseja mantê-lo em um só lugar. Mesmo se você precisar separá-lo em vários arquivos, deseje agrupá-los de alguma forma, para que seja mais fácil acessar esses dados a partir do código.
Então, imagine que você tenha milhares de linhas de dados dentro de um arquivo de origem. O compilador / intérprete precisa passar por todos esses dados cada vez que lê o arquivo e analisá-lo com o caro lexer & parser - mesmo que você não acesse esses dados nesta execução específica do programa. Além disso, quando você edita o código real nesse arquivo, precisa analisar os dados, o que dificulta todo o processo. Além disso, os arquivos de dados podem ser indexados. Dados codificados? Não muito...
procurando
Você tem muitos dados - é natural que você queira pesquisá-los.
Se você o armazenar em um banco de dados - poderá usar o idioma de consulta do banco de dados.
Se você o armazenar em um arquivo XML, poderá usar o XPath.
Se você o armazenar em JSON / YAML - poderá carregá-lo no REPL da sua linguagem de script favorita e pesquisá-lo.
Mesmo que você o armazene em um arquivo de texto antigo simples, já que ele possui uma estrutura que seu programa pode reconhecer, você pode usar grep / sed / awk para pesquisá-lo.
Embora seja verdade que você também possa grep / sed / awk através de dados codificados em um arquivo de origem, isso não funciona tão bem, pois sua consulta pode corresponder a outras linhas não relacionadas ou linhas perdidas que foram escritas de maneira diferente porque a sintaxe de representação de dados da linguagem de programação permite isso.
Existem ferramentas para pesquisar no código, mas são boas para encontrar declarações, não dados codificados.
Dito isto ...
É muito importante distinguir entre dados e código. Só porque algo está escrito como código não significa que não possa ser dados. E só porque algo é escrito com uma representação de dados não significa que não seja, de fato, código.
Eu tive uma aula quando tínhamos regras muito rígidas sobre "números mágicos" - não podíamos ter números em nosso código. Isso significa que tivemos que fazer coisas como:
o que é totalmente ridículo! Sim,
0
são tecnicamente "dados", mas fazem parte do código como o resto dofor
loop! Assim, mesmo que possa representá-lo como dados e separá-lo do código, isso não significa que deve . Não porque queremos deixar dados dentro do código, mas porque não são realmente dados - não mais do que o restante do código, que também é compilado em zeros e uns ...fonte
Eu acho que há alguma confusão acontecendo. Você está misturando duas coisas: "Separando código e dados" e "expressando o comportamento do programa como dados".
No seu caso, você está realmente preocupado com o segundo e misturando o primeiro nele. Quando você expressa o comportamento do programa como dados, facilita a extensão. No seu exemplo com
vowels = "aeiou"
, adicionar uma nova vogal é tão simples quanto adicionar um caractere. Se você tiver esses dados externamente, poderá alterar esse comportamento sem precisar recompilar o programa.E quando você pensa sobre isso, OOP é uma extensão desse pensamento. A ligação de dados e comportamento em conjunto permitirá alterar o comportamento do programa com base nos dados do programa.
fonte
ï
por um segundo; 'Vamos Conversar' sobrey
ew
!) Mover a lista para um banco de dados não vai consertar isso, e é realmente prejudicial - é complexidade que vai ser inútil se feito errado, mas você não vai sabe mesmo o que "errado" é a menos que você está projetando para i18n a partir do zero. Nesse ponto, você já está percebendo que uma lista de vogais simplesmente não será suficiente.Armazenar a configuração externamente permite que você tenha uma versão do código que funcione com muitas configurações; a alternativa é manter muitas versões do software que diferem apenas pela configuração.
Você mencionou vogais = "aeiou", e se eu quiser "y", devo reconstruir o programa inteiro? Posso atualizar versões facilmente agora que modifiquei o código? Se houver um erro, eu o causei ou o programa está quebrado?
Se isso estiver dentro do seu programa, isso implica que ele não espera que os usuários alterem a definição de vogais sem escanear o código para ver os possíveis efeitos colaterais. Se a definição for armazenada externamente, isso implica que o programa não deve ser interrompido por nenhum valor razoável definido na configuração.
Alguns vêem o contrário, ou seja, você está removendo o tumor do código de seus dados preciosos, veja: A citação de Torvalds sobre um bom programador
fonte
Eu estava em um projeto em que o líder insistiu em colocar dados de referência em pequenas tabelas, e achei que isso era bobagem. Mas como já tínhamos nossa infraestrutura de persistência e conectividade configuradas, acabou sendo um custo bastante baixo, além das outras operações de persistência que estávamos realizando.
Agora, ainda acho que foi uma decisão tola e, se não tivéssemos a infraestrutura disponível, simplesmente não a teríamos.
Mas alguns dos argumentos a favor que vejo são:
Além disso, às vezes a política atrapalha as práticas de codificação. Por exemplo, trabalhei em várias lojas nas quais enviar um arquivo .xml é A-OK, enquanto tocar em uma linha no código requer um ciclo de regressão completo e talvez um teste de carga. Portanto, havia uma equipe em que meus arquivos .xml do projeto eram extremamente ricos (e talvez -heh- possa conter algum código).
Sempre me pergunto se vou aproveitar o benefício de inserir dados do código em um repositório de dados externo, mesmo que seja apenas um arquivo de texto, mas trabalhei com pessoas que vêem dessa maneira o primeiro impulso.
fonte
Deixe-me fazer uma contra-pergunta completamente séria: qual, na sua opinião, é a diferença entre "dados" e "código"?
Quando ouço a palavra "dados", penso em "estado". Os dados são, por definição, o que o próprio aplicativo foi projetado para gerenciar e, portanto, o que o aplicativo nunca pode saber em tempo de compilação. Não é possível codificar os dados porque, assim que você os codifica, eles se tornam comportamento - não dados.
O tipo de dados varia de acordo com o aplicativo; um sistema de faturamento comercial pode armazenar informações de clientes e pedidos em um banco de dados SQL e um programa de gráficos vetoriais pode armazenar dados e metadados de geometria em um arquivo binário. Nos dois casos e em todas as etapas, há uma separação clara e inquebrável entre o código e os dados. Os dados pertencem ao usuário , não ao programador, portanto nunca podem ser codificados.
O que você parece estar falando é usar a descrição tecnicamente mais precisa disponível para o meu vocabulário atual: informações que governam o comportamento do programa que não estão escritas na linguagem de programação primária usada para desenvolver a maioria do aplicativo.
Mesmo essa definição, que é consideravelmente menos ambígua do que apenas a palavra "dados", tem alguns problemas. Por exemplo, e se partes significativas do programa forem escritas em diferentes idiomas? Eu pessoalmente trabalhei em vários projetos que são cerca de 50% C # e 50% JavaScript. O código JavaScript é "data"? A maioria das pessoas diria que não. E o HTML, são esses "dados"? A maioria das pessoas ainda diz não.
E o CSS? São dados ou código? Se pensarmos no código como algo que controla o comportamento do programa, o CSS não é realmente um código, porque apenas (bem, principalmente) afeta a aparência, não o comportamento. Mas também não são realmente dados; o usuário não é o proprietário, o aplicativo nem mesmo é o proprietário. É o equivalente ao código para um designer de interface do usuário. É como código , mas não é exatamente código.
Eu poderia chamar CSS de um tipo de configuração, mas uma definição mais prática é que é simplesmente código em uma linguagem específica de domínio . É isso que seu XML, YAML e outros "arquivos formatados" geralmente representam. E a razão pela qual usamos uma linguagem específica de domínio é que, de um modo geral, é simultaneamente mais concisa e mais expressiva em seu domínio específico do que codificando as mesmas informações em uma linguagem de programação de uso geral como C ou C # ou Java.
Você reconhece o seguinte formato?
Tenho certeza que a maioria das pessoas faz; é JSON . E aqui está a coisa interessante sobre o JSON: no JavaScript, é claramente um código e, em qualquer outra linguagem, são dados claramente formatados. Quase toda linguagem de programação convencional possui pelo menos uma biblioteca para "analisar" o JSON.
Se usarmos exatamente a mesma sintaxe dentro de uma função em um arquivo JavaScript, não poderá ser outra coisa senão código. E, no entanto, se pegarmos esse JSON, empurrá-lo em um
.json
arquivo e analisá-lo em um aplicativo Java, de repente são "dados". Isso realmente faz sentido?Argumento que o "data-ness" ou "configuration-ness" ou "code-ness" é inerente ao que está sendo descrito, não como está sendo descrito.
Se o seu programa precisar de um dicionário de 1 milhão de palavras para, por exemplo, gerar uma senha aleatória, você deseja codificá-lo da seguinte forma:
Ou você simplesmente colocaria todas essas palavras em um arquivo de texto delimitado por linhas e instruiria seu programa a ler? Realmente não importa se a lista de palavras nunca muda, não é uma questão de saber se você está codificando ou codificando (que muitos consideram corretamente um anti-padrão quando aplicado de maneira inadequada), é simplesmente uma questão de qual formato é mais eficiente e facilita a descrição do "material", qualquer que seja o "material". É bastante irrelevante se você chama de código ou dados; são as informações que seu programa requer para executar e um formato de arquivo simples é a maneira mais conveniente de gerenciá-lo e mantê-lo.
Supondo que você siga as práticas apropriadas, todo esse material está entrando no controle de origem, então você pode chamá-lo de código, apenas codificar em um formato diferente e talvez muito minimalista. Ou você pode chamá-lo de configuração, mas a única coisa que realmente diferencia o código da configuração é se você o documenta ou não e diz aos usuários finais como alterá-lo. Talvez você possa inventar algum argumento falso sobre a configuração que está sendo interpretada no momento da inicialização ou no tempo de execução e não no tempo de compilação, mas então você começaria a descrever várias linguagens de tipo dinâmico e quase certamente qualquer coisa com um mecanismo de script incorporado nela (por exemplo, maioria dos jogos). Código e configuração são tudo o que você decide rotulá-los como, nada mais, nada menos.
Agora, não é um perigo para a externalização de informação que não é realmente seguro para modificar (veja o link "soft codificação" acima). Se você externalizar sua matriz de vogais em um arquivo de configuração e documentá-lo como um arquivo de configuração para seus usuários finais, estará oferecendo a eles uma maneira quase infalível de interromper instantaneamente seu aplicativo, por exemplo, colocando "q" como vogal. Mas esse não é um problema fundamental da "separação de código e dados", é simplesmente um mau senso de design.
O que digo aos desenvolvedores juniores é que eles devem sempre externalizar as configurações que eles esperam mudar por ambiente. Isso inclui coisas como cadeias de conexão, nomes de usuário, chaves de API, caminhos de diretório e assim por diante. Eles podem ser os mesmos na sua caixa de desenvolvimento e na produção, mas provavelmente não, e os administradores de sistemas decidirão como eles querem que seja na produção, não nos desenvolvedores. Portanto, é necessário ter um grupo de configurações aplicadas em algumas máquinas e outras aplicadas em outras máquinas - ergo, arquivos de configuração externos (ou configurações em um banco de dados etc.)
Mas enfatizo que simplesmente colocar alguns "dados" em um "arquivo" não é o mesmo que externalizá-los na configuração. Colocar um dicionário de palavras em um arquivo de texto não significa que você deseja que os usuários (ou TI) o alterem, é apenas uma maneira de tornar muito mais fácil para os desenvolvedores entenderem o que está acontecendo e, se necessário, tornar mudanças ocasionais. Da mesma forma, colocar as mesmas informações em uma tabela de banco de dados não conta necessariamente como externalização de comportamento, se a tabela é somente leitura e / ou os DBAs são instruídos a nunca se ferrar com ela. A configuração implica que os dados são mutáveis, mas, na realidade, são determinados pelo processo e pelas responsabilidades, e não pela escolha do formato.
Então, para resumir:
"Código" não é um termo rigidamente definido. Se você expandir sua definição para incluir linguagens específicas de domínio e qualquer outra coisa que afete o comportamento, grande parte desse aparente atrito simplesmente desaparecerá e tudo fará sentido. Você pode ter um "código" DSL não compilado em um arquivo simples.
"Dados" implica em informações pertencentes ao (s) usuário (s) ou pelo menos a alguém que não seja o desenvolvedor, e que geralmente não estão disponíveis em tempo de design. Não poderia ser codificado, mesmo que você quisesse. Com a possível exceção do código auto-modificável , a separação entre código e dados é uma questão de definição, não de preferência pessoal.
A "codificação suave" pode ser uma prática terrível quando aplicada em excesso, mas nem toda instância de externalização constitui necessariamente uma codificação flexível, e muitas instâncias de armazenamento de informações em "arquivos simples" não são necessariamente uma tentativa genuína de externalização.
A configuração é um tipo especial de soft-de codificação que é necessário por causa do conhecimento que o aplicativo pode precisar executar em ambientes diferentes. A implantação de um arquivo de configuração separado junto com o aplicativo é muito menos trabalhosa (e muito menos perigosa) do que a implantação de uma versão diferente do código em todos os ambientes. Portanto, alguns tipos de soft-coding são realmente úteis.
fonte
Sugiro a leitura deste artigo clássico de Oren Eini (também conhecido como Ayende Rahien)
http://ayende.com/blog/3545/enabled-change-by-hard-coding-everything-the-smart-way
Meu argumento principal é focar na simplicidade e legibilidade. Isso pode significar que é improvável que coisas que provavelmente não serão reconfiguradas sejam deixadas codificadas (de forma legível). Isso permite que você use a sintaxe completa de uma linguagem de programação para expressar os parâmetros, além de obter efeitos colaterais benéficos, como conclusão de código e erros de compilação no uso indevido.
Dessa forma, você potencialmente evita as complexidades de analisar / interpretar ("mas alguém analisa meu YAML / JSON" - mapear o texto analisado nas chamadas específicas da API pode ser uma forma de interpretação) e evitar a complexidade de outra etapa entre os "dados "e seu uso.
Alguns casos se prestam a serem expressos em dados, mesmo em um cenário como este: por exemplo, especificar milhares de pontos no espaço 3D pode ser mais adequado para um arquivo de texto do que código, embora em alguns idiomas, incluindo C usando inicializadores de estrutura, código pode ser apropriado mesmo para isso.
fonte
Ok, vamos supor que você queira escrever algum tipo de programa c ++ para seu lazer. Você sabe exatamente o que tem que fazer e o que nunca precisará fazer. Agora pegue qualquer livro sobre "design de software moderno". Aqui está a regra do jogo: para todas as classes do seu projeto e para todos os casos tão pequenos, você deve implementar todos os padrões sofisticados que você encontrar descritos nesse livro para tornar seu código um "design limpo". Bem, "injeção de dependência" será suficiente para muitas pessoas, eu acho. (É c ++, não java!) A programação é ensinada de um ponto de vista cada vez mais teórico. Não é suficiente que você faça o trabalho, você precisa escrever um código que possa ser mantido, que seja tolo ... tudo bem e certo. O problema começa quando pessoas. pare de pensar sobre o motivo real, os padrões de design foram inventados e se tornaram dogmáticos.
Deixe-me impedi-lo de escrever sua ferramenta de contagem de letras usando (acima) um único princípio simples de design: Quando você escreve um código que executa um determinado trabalho em dados de entrada de um determinado tipo, verifique se ele é capaz de executar essa tarefa em qualquer entrada. dados desse tipo. - Quando você deseja escrever uma ferramenta de contagem de letras, faz sentido escrevê-la de uma maneira, para que não apenas seja possível contar vogais, mas "qualquer letra". - Como você talvez não saiba qual é o corpus que está analisando, também pode escolher uma codificação muito geral (UTF-16) e cobrir a maioria (todos?) Dos idiomas escritos e seus símbolos.
Até esse ponto, temos uma função com dois argumentos (o corpus e as letras a serem contadas). Estamos preocupados apenas em encontrar um "tipo" ou "classe" razoavelmente geral que as letras também pertençam: certamente podemos fazer melhor que os símbolos ASCII!
Digite um demônio que empunhe o dogma "generalização e reutilização": - Por que não contar qualquer símbolo de qualquer classe em um fluxo de entrada dessa classe? (resumo de letras para seqüências de bits de tamanho arbitrário, mas finito, pois é o mais geral que você pode obter com um computador ...) - Espere, mesmo assim ainda estamos contando em números naturais. No entanto, a contagem pode ser generalizada como um mapeamento de um conjunto contável para ele mesmo, cumprindo os axiomas ... [você entendeu]
Agora esse exemplo pode ser bobo, mas se você considerar tarefas de design mais complexas do que uma ferramenta de contagem, poderá encontrar toda a oportunidade de introduzir abstração adicional necessária de acordo com algum tipo de padrão de design encontrado em seu livro.
A separação de "dados" e "código" provavelmente será trivial (argumentos da função) ou você se encontrará tratando os invariantes como variáveis ("dados").
Se houver alguma confusão, é provável que "interfaces" e "serviços" e todos os detalhes de classe (por exemplo, tipos) sejam subitamente "dados", ou seja, dependências a serem injetadas externamente. Eu sinto que os cursos de informática ministrados na universidade se tornaram muito parecidos com aulas de filosofia e há menos tempo para projetos reais, para que os alunos possam adquirir experiência em como criar software que funcione. Se você já se perguntou por que precisa usar um padrão incrivelmente complexo em vez de uma solução óbvia, esse desenvolvimento é (provavelmente) como esse requisito foi "criado" ...
Para o seu problema específico: 1. Se você pudesse 1.) escrever um programa com o máximo de código fixo para o seu caso específico e depois 2.) generalizar a partir desse código de maneira direta, por exemplo. introduzindo mais argumentos de função e usando outros "padrões triviais", você pode ter certeza de que está separando código e dados, da maneira óbvia, como foi feito desde que a programação funcional foi inventada. (ofc você pula 1. e faz 2. instantaneamente ...)
Qualquer coisa não óbvia aqui provavelmente é um caso de "impasse teórico": como escrever uma interface referindo-se a uma interface e mais uma interface ... e, no final, você possui um pequeno arquivo xml para configurar todas essas interfaces e as dependências a serem injetadas na sua confusão de interface de classe.
Vamos apenas torcer para que o xml-parser que você precisa não precise de um xml-config para funcionar ...
fonte