Des chaînes de caractères qui ne changeront jamais

39

Donc, dans mes efforts pour écrire un programme de conjugaison de verbes (en utilisant un jeu de données) pour le français, j'ai rencontré un léger problème.

L'algorithme permettant de conjuguer les verbes est en fait assez simple pour les cas de verbes d'environ 17 ans, et utilise un modèle particulier pour chaque cas; ainsi, les suffixes de conjugaison pour ces 17 classes sont statiques et ne changeront (très probablement) pas de sitôt. Par exemple:

// 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"]
    };

Ce sont des suffixes flexionnels pour la classe de verbe la plus courante en français.

Il existe d'autres classes de verbes (irréguliers), dont les conjugaisons resteront très probablement statiques pendant un ou deux siècles. Étant donné qu’elles sont irrégulières, leurs conjugaisons complètes doivent être incluses statiquement, car elles ne peuvent pas être conjuguées de manière fiable à partir d’un motif (il n’ya également que 32 personnes irrégulières). Par exemple:

// "ê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"]
    };

Je pourrais mettre tout cela en XML ou même en JSON et le désérialiser au besoin, mais y a-t-il un objectif? Ces chaînes font partie du langage naturel, qui change, mais à un rythme lent.

Ce qui me préoccupe, c’est qu’en agissant de la manière «correcte» et en désérialisant certaines sources de données, j’ai non seulement compliqué le problème, qui n’a pas besoin d’être compliqué, mais aussi complètement relégué au second plan. approche algorithmique: ne pas utiliser une source de données! En C #, je pourrais simplement créer une classe sous namespace Verb.Conjugation(par exemple class Irregular) pour héberger ces chaînes dans un type énuméré ou quelque chose du genre, au lieu de les insérer dans XML et de créer un fichier class IrregularVerbDeserializer.

Donc, la question: est-il approprié de coder en dur des chaînes qui sont très peu susceptibles de changer pendant la durée de vie d'une application? Bien sûr, je ne peux pas garantir à 100% qu'ils ne changeront pas, mais le rapport coût / risque est presque trivial à peser à mes yeux - le codage en dur est la meilleure idée ici.

Edit : le doublon proposé demande comment stocker un grand nombre de chaînes statiques , alors que ma question est de savoir quand devrais-je coder en dur ces chaînes statiques .

Chris Cirefice
la source
26
Voulez-vous utiliser ce logiciel pour une langue autre que le français à l'avenir?
10
Approche algorithmique ou non, il est clair que vous devez simplement coder en dur ces 32 * 20 chaînes (et plus si vous ajoutez plus de langues), et la seule vraie question est de savoir où les placer. Je choisirais le lieu qui vous convient le mieux, ce qui semble être du code pour le moment. Vous pouvez toujours les mélanger plus tard.
Ixrec
1
@ChrisCirefice Cela me semble plutôt optimal. Fonce.
Ixrec
2
@Gusdor, je ne pense pas que vous lisiez clairement - j'ai dit que les modèles de conjugaison ne changeraient probablement jamais, ou changeaient si peu fréquemment qu'une recompilation tous les 100 ans environ serait acceptable. Bien sûr, le code va changer, mais une fois que les chaînes sont dans la manière que je veux, à moins que je ne les refacture, elles seront statiques pendant les 100 prochaines années.
Chris Cirefice
1
+1 Sans compter que dans 60 à 100 ans, le coût n'existera pas ou aura été remplacé par une version améliorée.
HarryCBurn

Réponses:

56

Est-il approprié de coder en dur des chaînes dont il est très peu probable qu'elles changent pendant la durée de vie d'une application? Bien sûr, je ne peux pas garantir à 100% qu'ils ne changeront pas, mais le rapport coût / risque est presque trivial à peser à mes yeux - le codage en dur est la meilleure idée ici

Il me semble que vous avez répondu à votre propre question.

L'un des plus grands défis à relever consiste à séparer les éléments susceptibles de changer des éléments qui ne changeront pas. Certaines personnes deviennent fous et jettent absolument tout ce qu'elles peuvent dans un fichier de configuration. D'autres vont à l'autre extrême et nécessitent une recompilation, même pour les changements les plus évidents.

Je choisirais l'approche la plus simple à mettre en œuvre jusqu'à ce que je trouve une raison impérieuse de compliquer les choses.

Dan Pichelman
la source
Merci Dan, c'est un peu ce que j'ai pensé. Écrire un schéma XML pour cela, avoir un autre fichier à garder en mémoire, et devoir écrire une interface pour désérialiser les données me paraissait exagéré, vu qu'il n'y avait tout simplement pas beaucoup de chaînes, et parce que c'est un langage naturel, il est peu probable qu'il change radicalement dans les 100 prochaines années. Heureusement, de nos jours, dans les langages de programmation, nous avons des moyens sophistiqués d’abréger ces données brutes derrière une interface attrayante, French.Verb.Irregular.Etrecontenant par exemple les données de ma question. Je pense que ça marche très bien;)
Chris Cirefice
3
+1 Ici, à partir du camp Ruby, je commencerais par coder en dur et le déplacer dans la configuration si nécessaire. Ne modifiez pas prématurément votre projet en rendant les choses configurables. Cela vous ralentit.
Overbryd
2
Remarque: certains groupes ont une définition différente de «codage en dur», alors sachez que ce terme signifie plusieurs choses. Il existe un anti-modèle bien reconnu dans lequel vous codez des valeurs dans les instructions d'une fonction, plutôt que de créer des structures de données comme vous l'avez fait ( if (num == 0xFFD8)). Cet exemple devrait devenir quelque chose comme if (num == JPEG_MAGIC_NUMBER)dans presque tous les cas pour des raisons de lisibilité. Je le signale simplement parce que le mot "codage en dur" soulève souvent les cheveux sur le cou des gens (comme le mien) à cause de cette autre signification du mot.
Cort Ammon
@CortAmmon JPEG a beaucoup de nombres magiques. Sûrement JPEG_START_OF_IMAGE_MARKER?
user253751
@immibis Votre choix de nommage constant est probablement meilleur que le mien.
Cort Ammon
25

Vous raisonnez sur une mauvaise portée.

Vous n'avez pas codé en dur uniquement des verbes individuels. Vous avez codé en dur le langage et ses règles . Ceci, à son tour, signifie que votre application ne peut pas être utilisée pour une autre langue et ne peut pas être étendue avec d'autres règles.

Si telle est votre intention (c’est-à-dire l’utiliser uniquement en français), c’est la bonne approche, à cause de YAGNI. Mais vous admettez vous-même que vous souhaitez l'utiliser ultérieurement pour d'autres langues également, ce qui signifie que très bientôt, vous devrez de toute façon transférer toute la partie codée en dur dans les fichiers de configuration. La question restante est:

  • Voulez-vous, avec une certitude proche de 100%, dans un avenir proche, étendre l'application à d'autres langues? Si tel est le cas, vous devriez déjà exporter des éléments vers des fichiers JSON ou XML (pour des mots, des parties de mots, etc.) et des langages dynamiques (pour des règles) au lieu de vous forcer à réécrire la majeure partie de votre application.

  • Ou bien, il existe une faible probabilité que l'application soit étendue quelque part dans le futur. Dans ce cas, YAGNI indique que l'approche la plus simple (celle que vous utilisez actuellement) est la meilleure?

À titre d’illustration, prenons le vérificateur d’orthographe de Microsoft Word. Combien de choses pensez-vous sont codées en dur?

Si vous développez un traitement de texte, vous pouvez commencer par une simple moteur d'orthographe avec les règles et même des mots codés en dur codées en dur: if word == "musik": suggestSpelling("music");. Rapidement, vous commencez à déplacer les mots, puis à se contrôler en dehors de votre code. Autrement:

  • Chaque fois que vous devez ajouter un mot, vous devez recompiler.
  • Si vous avez appris une nouvelle règle, vous devez modifier le code source à nouveau.
  • Et plus important encore, il n’est pas possible d’adapter le moteur à l’allemand ou au japonais sans écrire d’énormes quantités de code.

Comme vous l'avez souligné vous-même:

Très peu de règles du français pourraient être appliquées au japonais.

Dès que vous coderez en dur les règles d'une langue, toutes les autres exigeront de plus en plus de code, en particulier compte tenu de la complexité des langues naturelles.

Un autre sujet est la façon dont vous exprimez ces différentes règles, si ce n'est par le code. En fin de compte, vous constaterez peut-être qu'un langage de programmation est le meilleur outil pour cela. Dans ce cas, si vous avez besoin d'étendre le moteur sans le recompiler, les langages dynamiques peuvent constituer une bonne alternative.

Arseni Mourzenko
la source
1
Bien sûr, tout n’est pas codé en dur ici: P, donc je suppose que c’est vraiment déterminer ce que je veux que l’interface ressemble afin que je puisse l’appliquer à plusieurs langues. Le problème est que je ne connais pas encore suffisamment toutes les langues, ce qui est effectivement impossible. Je pense que la seule chose qui vous manque peut-être, c’est que les schémas de conjugaison (c’est tout ce dont je parle) sont très statiques dans une langue, et c’est vraiment quelque chose qui est au cas par cas. Il y a environ 17 modèles de conjugaison en français pour les verbes. Cela ne va pas durer trop longtemps ...
Chris Cirefice
4
Je ne suis pas d'accord - je ne pense pas qu'il soit logique de déplacer quoi que ce soit en dehors du code avant que cela ne vienne naturellement à travers la refactorisation. Commencez avec un langage, ajoutez-en d'autres - à un moment donné, l'implémentation d'ILanguageRule partagera suffisamment de code pour qu'il soit simplement plus efficace de paramétrer une implémentation unique avec un fichier XML (ou un autre fichier). Mais même dans ce cas, vous pourriez vous retrouver avec un japonais dont la structure est complètement différente. Commencer en poussant votre interface à être au format XML (ou similaire) ne fait que demander des modifications dans l'interface plutôt que dans la mise en œuvre.
ptyx
2
Remarque: si vous souhaitez ajouter plus de langues, cela ne signifie pas que vous devez déplacer les langues dans un fichier de configuration! Vous pourriez également avoir une LanguageProcessorclasse avec plusieurs sous-classes. (En réalité, le "fichier de configuration" est en fait une classe)
user253751
2
@MainMa: Pourquoi considérez-vous comme un problème de recompiler lors de l'ajout d'un mot? De toute façon, vous devez recompiler lorsque vous modifiez le code, et la liste de mots est probablement la partie du code la moins susceptible de changer avec le temps.
JacquesB
3
Je soupçonne que la flexibilité de pouvoir coder les règles grammaticales très spécifiques de chaque langue dans une sous-classe serait finalement plus pratique que de pouvoir charger ces mêmes règles à partir d’un fichier de configuration (parce que vous écririez votre propre langage de programmation pour interpréter les configurations).
David K
15

Les chaînes doivent être extraites dans un fichier de configuration ou une base de données lorsque les valeurs peuvent changer indépendamment de la logique du programme.

Par exemple:

  • Extraction de textes d'interface utilisateur dans des fichiers de ressources. Cela permet à un non-programmeur d'éditer et de relire les textes, et d'ajouter de nouvelles langues en ajoutant de nouveaux fichiers de ressources localisés.

  • Extraction de chaînes de connexion, d’URL vers des services externes, etc., vers des fichiers de configuration. Cela vous permet d'utiliser différentes configurations dans différents environnements et de modifier les configurations à la volée, car elles peuvent devoir être modifiées pour des raisons externes à votre application.

  • Un correcteur orthographique qui a un dictionnaire de mots à vérifier. Vous pouvez ajouter de nouveaux mots et langues sans modifier la logique du programme.

Cependant, l'extraction vers la configuration entraîne une complexité supplémentaire qui n'a pas toujours de sens.

Les chaînes peuvent être codées en dur lorsque la chaîne réelle ne peut pas changer sans changer la logique du programme.

Exemples:

  • Un compilateur pour un langage de programmation. Les mots-clés ne sont pas extraits dans une configuration, car chaque mot-clé a une sémantique spécifique qui doit être prise en charge par le code dans le compilateur. L'ajout d'un nouveau mot clé nécessitera toujours des modifications de code. Par conséquent, aucune valeur d'extraction des chaînes dans un fichier de configuration n'est nécessaire.
  • Implémentation d'un protocole: Ex. un client HTTP aura des chaînes codées en dur telles que "GET", "content-type", etc. Ici, les chaînes font partie de la spécification du protocole, de sorte qu'elles sont les parties du code les moins susceptibles de changer.

Dans votre cas, je pense qu'il est clair que les mots font partie intégrante de la logique du programme (puisque vous construisez un conjugateur avec des règles spécifiques pour des mots spécifiques) et que l'extraction de ces mots dans un fichier externe n'a aucune valeur.

Si vous ajoutez une nouvelle langue, vous devrez quand même ajouter un nouveau code, car chaque langue a une logique de conjugaison spécifique.


Certains ont suggéré d'ajouter un type de moteur de règles permettant de spécifier des règles de conjugaison pour des langues arbitraires, afin que de nouvelles langues puissent être ajoutées uniquement par configuration. Réfléchissez bien avant de vous engager dans cette voie, car les langages humains sont merveilleusement étranges. Vous avez donc besoin d'un moteur de règles très expressif. Vous inventeriez essentiellement un nouveau langage de programmation (un DSL de conjugaison) pour un bénéfice douteux. Mais vous avez déjà à votre disposition un langage de programmation qui peut faire tout ce dont vous avez besoin. En tout cas, YAGNI.

JacquesB
la source
1
En fait, dans un commentaire adressé à MainMa, j’ai mentionné qu’écrire un DSL à cet effet serait inutile, car très peu de langues naturelles sont suffisamment similaires pour en valoir la peine. Peut-être que le français, l’espagnol et l’italien seraient suffisamment proches , mais ne méritaient pas vraiment l’effort supplémentaire étant donné que le nombre de règles est très statique dans une langue donnée. Les autres points que vous avez mentionnés sur la complexité étaient mes inquiétudes exactes, et je pense que vous avez parfaitement compris ce que je vous demandais dans ma question et avez donné une excellente réponse avec des exemples, alors +1!
Chris Cirefice
5

Je suis tout à fait d'accord avec la réponse de Dan Pichelman, mais je voudrais ajouter une chose. La question que vous devriez vous poser ici est "qui va maintenir / allonger / corriger la liste de mots?". Si c'est toujours la personne qui maintient également les règles d'un langage spécifique (le développeur en particulier, je suppose vous), alors il n'y a aucun intérêt à utiliser un fichier de configuration externe si cela complique les choses - vous n'obtiendrez aucun avantage cette. De ce point de vue, il sera logique de coder en dur de telles listes de mots, même si vous devez les changer de temps en temps, dans la mesure où il suffit de fournir une nouvelle liste dans le cadre d'une nouvelle version.

(Par contre, s'il y a une faible chance que quelqu'un d'autre puisse être capable de maintenir la liste à l'avenir, ou si vous devez modifier les listes de mots sans déployer une nouvelle version de votre application, utilisez un fichier séparé.)

Doc Brown
la source
C'est un bon point - cependant, il est fort probable que je serai la seule personne qui maintiendra réellement le code, au moins pour les prochaines années. La bonne partie de ceci est que même si les chaînes seront codées en dur, il s’agit d’un très petit ensemble de chaînes / règles qui ne risquent pas de changer de si tôt (car il s’agit d’un langage naturel qui n’évolue pas trop -an). Cela dit, les règles de conjugaison, les chaînes de terminaison de verbe, etc. seront vraisemblablement les mêmes pour notre vie :)
Chris Cirefice
1
@ChrisCirefice ": exactement ce que je veux dire.
Doc Brown
2

Même si le codage en dur semble correct ici, et mieux que le chargement dynamique de fichiers de configuration, je vous recommande néanmoins de séparer strictement vos données (le dictionnaire des verbes) de l' algorithme . Vous pouvez les compiler directement dans votre application lors du processus de construction.

Cela vous fera économiser beaucoup de temps avec le maintien de la liste. Dans votre VCS, vous pouvez facilement identifier si un commit a bien changé l'algorithme, ou simplement corriger un bogue de conjugaison. En outre, la liste devra peut-être être ajoutée à l'avenir pour les cas non pris en compte. Surtout, le nombre de 32 verbes irréguliers que vous avez comptés ne semble pas être exact. Bien que ceux-ci semblent couvrir ceux qui sont couramment utilisés, j'ai trouvé des références à 133 voire 350 d'entre eux.

Bergi
la source
Bergi, j'avais prévu de séparer les données de l'algorithme. Ce que vous notez à propos des irréguliers français - la définition de irrégulier est au mieux mal comprise. Ce que je veux dire quand je dis irrégulier, ce sont les verbes qui ne peuvent pas être «calculés» ou conjugués à partir de leur seule forme infinitive. Les verbes irréguliers n'ont pas de structure particulière du tout et ont donc besoin d'une liste explicite de leurs conjugaisons (sous French.Verb.Conjugation.Irregular` par exemple). Techniquement, leurs verbes sont «irréguliers», mais ils ont en fait un modèle de conjugaison fixe :)
Chris Cirefice
0

La partie importante est la séparation des préoccupations. Comment vous y parvenez est moins pertinent. c'est-à-dire que Java va bien.

Indépendamment de la manière dont les règles sont exprimées, devriez-vous ajouter une langue pour modifier une règle: combien de codes et de fichiers devez-vous modifier?

Idéalement, l'ajout d'une nouvelle langue devrait être possible en ajoutant un fichier 'english.xml' ou un nouvel objet 'EnglishRules implémente ILanguageRules'. Un fichier texte (JSON / XML) vous donne un avantage si vous souhaitez le modifier en dehors de votre cycle de vie de génération, mais nécessitant une grammaire complexe, une analyse syntaxique, et sera plus difficile à déboguer. Un fichier de code (Java) vous permet d’exprimer des règles complexes de manière plus simple, mais nécessite une reconstruction.

Je commencerais par une simple API Java derrière une interface agnostique en langage clair - comme vous en avez besoin dans les deux cas. Si vous le souhaitez, vous pouvez toujours ajouter ultérieurement une implémentation de cette interface avec un fichier XML, mais je ne vois pas la nécessité de traiter ce problème immédiatement (ou jamais).

ptyx
la source