Assim, em meus esforços para escrever um programa para conjugar verbos (algoritmicamente, não através de um conjunto de dados) para o francês, deparei-me com um pequeno problema.
O algoritmo para conjugar os verbos é realmente bastante simples para os mais ou menos 17 casos de verbos e é executado em um padrão específico para cada caso; portanto, os sufixos de conjugação para essas 17 classes são estáticos e (muito provavelmente) não serão alterados tão cedo. Por exemplo:
// Verbs #1 : (model: "chanter")
terminations = {
ind_imp: ["ais", "ais", "ait", "ions", "iez", "aient"],
ind_pre: ["e", "es", "e", "ons", "ez", "ent"],
ind_fut: ["erai", "eras", "era", "erons", "erez", "eront"],
participle: ["é", "ant"]
};
Estes são sufixos flexionados para a classe de verbo mais comum em francês.
Existem outras classes de verbos (irregulares), cujas conjugações provavelmente também permanecerão estáticas nos próximos dois séculos. Como são irregulares, suas conjugações completas devem ser incluídas estaticamente, porque não podem ser conjugadas de maneira confiável a partir de um padrão (também existem apenas [pela minha conta] 32 irregulares). Por exemplo:
// "être":
forms = {
ind_imp: ["étais", "étais", "était", "étions", "étiez", "étaient"],
ind_pre: ["suis", "es", "est", "sommes", "êtes", "sont"],
ind_fut: ["serai", "seras", "sera", "serons", "serez", "seront"],
participle: ["été", "étant"]
};
Eu poderia colocar tudo isso em XML ou JSON e desserializá-lo quando precisar ser usado, mas há algum ponto? Essas cadeias fazem parte da linguagem natural, que muda, mas em um ritmo lento.
Minha preocupação é que, ao fazer as coisas da maneira "correta" e desserializar alguma fonte de dados, eu não apenas tenha complicado o problema que não precisa ser complicado, mas também tenha retrocedido completamente todo o objetivo do abordagem algorítmica: para não usar uma fonte de dados! Em C #, eu poderia apenas criar uma classe em namespace Verb.Conjugation
(por exemplo class Irregular
) para abrigar essas seqüências de caracteres em um tipo enumerado ou algo assim, em vez de colocá-las em XML e criar a class IrregularVerbDeserializer
.
Portanto, a pergunta: é apropriado para cadeias de código rígido que são muito pouco provável que a mudança durante o tempo de vida de uma aplicação? É claro que não posso garantir 100% de que eles não vão mudar, mas o risco versus o custo é quase trivial para pesar nos meus olhos - codificar é a melhor ideia aqui.
Edit : O duplicado proposto pergunta como armazenar um grande número de strings estáticas , enquanto minha pergunta é quando devo codificar essas strings estáticas .
Respostas:
Parece-me que você respondeu sua própria pergunta.
Um dos maiores desafios que enfrentamos é separar as coisas que provavelmente mudarão daquelas que não mudarão. Algumas pessoas ficam loucas e despejam absolutamente tudo o que podem em um arquivo de configuração. Outros vão para o outro extremo e exigem uma recompilação até para as mudanças mais óbvias.
Eu adotaria a abordagem mais fácil de implementar até encontrar um motivo convincente para torná-lo mais complicado.
fonte
French.Verb.Irregular.Etre
que conteria os dados da minha pergunta. Eu acho que funciona bem;)if (num == 0xFFD8)
). Esse exemplo deve se tornar algo comoif (num == JPEG_MAGIC_NUMBER)
em quase todos os casos por razões de legibilidade. Apenas aponto porque a palavra "hardcoding" geralmente arrepia o pescoço das pessoas (como o meu) por causa desse significado alternativo da palavra.JPEG_START_OF_IMAGE_MARKER
?Você está raciocinando no escopo errado.
Você não codificou apenas verbos individuais. Você codificou o idioma e suas regras . Por sua vez, isso significa que seu aplicativo não pode ser usado para qualquer outro idioma e não pode ser estendido com outras regras.
Se essa é sua intenção (por exemplo, usá-lo somente em francês), essa é a abordagem correta, devido ao YAGNI. Mas você admite que também deseja usá-lo posteriormente para outros idiomas, o que significa que muito em breve você precisará mover toda a parte codificada para os arquivos de configuração de qualquer maneira. A questão restante é:
Com uma certeza próxima de 100%, em um futuro próximo, estenderá o aplicativo para outros idiomas? Nesse caso, você deveria ter exportado coisas para arquivos JSON ou XML (para palavras, partes das palavras etc.) e linguagens dinâmicas (para regras) agora em vez de se forçar a reescrever a maior parte do seu aplicativo.
Ou há apenas uma pequena probabilidade de que o aplicativo seja estendido em algum lugar no futuro; nesse caso, o YAGNI dita que a abordagem mais simples (a que você está usando agora) é a melhor?
Como ilustração, use o verificador ortográfico do Microsoft Word. Quantas coisas você acha que estão codificadas?
Se você está desenvolvendo um processador de texto, você pode começar por um motor de ortografia simples, com regras hardcoded e palavras mesmo hardcoded:
if word == "musik": suggestSpelling("music");
. Rapidamente, você começará a mover as palavras e se autogovernará fora do seu código. De outra forma:Como você se destacou:
Assim que você codifica as regras de um idioma, todos os outros precisarão de mais e mais código, especialmente devido à complexidade das linguagens naturais.
Outro assunto é como você expressa essas regras diferentes, se não através do código. Por fim, você pode achar que uma linguagem de programação é a melhor ferramenta para isso. Nesse caso, se você precisar estender o mecanismo sem recompilá-lo, linguagens dinâmicas podem ser uma boa alternativa.
fonte
LanguageProcessor
classe com várias subclasses. (Efetivamente, o "arquivo de configuração" é na verdade uma classe)As strings devem ser extraídas para um arquivo de configuração ou banco de dados quando os valores puderem mudar independentemente da lógica do programa.
Por exemplo:
Extraindo textos da interface do usuário para arquivos de recursos. Isso permite que um não programador edite e revise os textos e permite adicionar novos idiomas adicionando novos arquivos de recursos localizados.
Extraindo cadeias de conexão, URLs para serviços externos etc. para arquivos de configuração. Isso permite que você use configurações diferentes em ambientes diferentes e altere as configurações rapidamente, pois elas podem precisar ser alteradas por motivos externos ao seu aplicativo.
Um corretor ortográfico que possui um dicionário de palavras para verificar. Você pode adicionar novas palavras e idiomas sem modificar a lógica do programa.
Mas também há uma sobrecarga de complexidade na extração para configuração, e nem sempre faz sentido.
As cadeias podem ser codificadas quando a cadeia real não pode ser alterada sem alterar a lógica do programa.
Exemplos:
No seu caso, acho claro que as palavras são parte integrante da lógica do programa (já que você está construindo um conjugador com regras específicas para palavras específicas) e extrair essas palavras para um arquivo externo não tem valor.
Se você adicionar um novo idioma, precisará adicionar um novo código de qualquer maneira, já que cada idioma possui uma lógica de conjugação específica.
Alguns sugeriram que você poderia adicionar algum tipo de mecanismo de regras que permita especificar regras de conjugação para idiomas arbitrários, para que novos idiomas possam ser adicionados apenas pela configuração. Pense com muito cuidado antes de seguir esse caminho, porque as línguas humanas são maravilhosamente estranhas, portanto você precisa de um mecanismo de regras muito expressivo. Basicamente, você estaria inventando uma nova linguagem de programação (uma DSL de conjugação) para benefício duvidoso. Mas você já tem uma linguagem de programação à sua disposição que pode fazer tudo o que você precisa. Em qualquer caso, YAGNI.
fonte
Concordo 100% com a resposta de Dan Pichelman, mas gostaria de acrescentar uma coisa. A pergunta que você deve fazer aqui é "quem vai manter / estender / corrigir a lista de palavras?". Se é sempre a pessoa que também mantém as regras de um idioma específico (o desenvolvedor em particular, acho), não faz sentido usar um arquivo de configuração externo se isso torna as coisas mais complexas - você não obterá nenhum benefício com isso. isto. Desse ponto de vista, fará sentido codificar essas listas de palavras, mesmo que você precise alterá-las periodicamente, desde que seja suficiente fornecer uma nova lista como parte de uma nova versão.
(Por outro lado, se houver uma pequena chance de alguém poder manter a lista no futuro, ou se você precisar alterar as listas de palavras sem implantar uma nova versão do seu aplicativo, use um arquivo separado.)
fonte
Mesmo que a codificação física pareça boa aqui, e melhor do que carregar dinamicamente os arquivos de configuração, eu ainda recomendo que você separe estritamente seus dados (o dicionário de verbos) do algoritmo . Você pode compilá-los diretamente no seu aplicativo no processo de compilação.
Isso economizará muito trabalho com a manutenção da lista. No seu VCS, você pode identificar facilmente se um commit mudou o algoritmo ou apenas corrigiu um erro de conjugação. Além disso, a lista pode precisar ser anexada no futuro para os casos que você não considerou. Especialmente, o número dos 32 verbos irregulares que você contou não parece ser exato. Enquanto esses parecem abranger os mais usados, encontrei referências a 133 ou mesmo a 350 deles.
fonte
A parte importante é a separação de preocupações. Como você consegue isso é menos relevante. ou seja, Java está bem.
Independentemente de como as regras são expressas, você deve adicionar um idioma para alterar uma regra: quantos códigos e arquivos você precisa editar?
Idealmente, a adição de um novo idioma deve ser possível adicionando um arquivo 'english.xml' ou um novo 'EnglishRules implementa o objeto ILanguageRules'. Um arquivo de texto (JSON / XML) oferece uma vantagem se você deseja alterá-lo fora do ciclo de vida da construção, mas requer uma gramática complexa, análise e será mais difícil depurar. Um arquivo de código (Java) permite expressar regras complexas de uma maneira mais simples, mas requer uma reconstrução.
Eu começaria com uma API Java simples por trás de uma interface independente de linguagem limpa - conforme necessário nos dois casos. Você sempre pode adicionar uma implementação dessa interface apoiada por um arquivo XML posteriormente, se desejar, mas não vejo a necessidade de resolver esse problema imediatamente (ou nunca).
fonte