Comment la séparation du code et des données est-elle devenue une pratique?

29

Veuillez lire attentivement la question: elle demande comment , pas pourquoi .

Je suis récemment tombé sur cette réponse , qui suggère d'utiliser une base de données pour stocker des données immuables:

Il semble que la plupart des nombres magiques que vous décrivez - en particulier s'ils dépendent d'une partie - sont vraiment des données, pas du code. [...] Cela peut signifier une base de données de type SQL ou simplement un fichier texte formaté.

Il me semble que si vous avez des données qui font partie de ce que fait votre programme, alors la chose à faire est de les mettre dans le programme . Par exemple, si la fonction de votre programme est de compter les voyelles, qu'y a-t-il de mal à y avoir vowels = "aeiou"? Après tout, la plupart des langues ont des structures de données conçues précisément pour cette utilisation. Pourquoi voudriez-vous prendre la peine de séparer les données en les mettant dans un "fichier texte formaté", comme suggéré ci-dessus? Pourquoi ne pas simplement faire ce fichier texte formaté dans le langage de programmation de votre choix? Est-ce maintenant une base de données? Ou est-ce du code?

Je suis sûr que certains penseront que c'est une question stupide, mais je la pose avec sérieux. J'ai l'impression que "du code et des données séparés" émergent culturellement comme une sorte de vérité évidente, avec d'autres choses évidentes comme "ne donnez pas de noms trompeurs à vos variables" et "n'évitez pas d'utiliser des espaces simplement parce que votre langue le considère c'est insignifiant ".

Prenons par exemple cet article: Le problème de la séparation des données du code de marionnette . Le problème ? Quel problème? Si Puppet est un langage pour décrire mon infrastructure, pourquoi ne peut-il pas également décrire que le serveur de noms est 8.8.8.8? Il me semble que le problème n'est pas que le code et les données sont mêlèrent, 1 mais Puppet manque des structures de données suffisamment riche et les moyens d'interface avec d'autres choses.

Je trouve ce changement inquiétant. La programmation orientée objet a déclaré "nous voulons des structures de données arbitrairement riches", et donc doté de structures de données avec des pouvoirs de code. Vous obtenez en conséquence l'encapsulation et l'abstraction. Même les bases de données SQL ont des procédures stockées. Lorsque vous séquestrez des données dans YAML ou des fichiers texte ou des bases de données stupides comme si vous supprimiez une tumeur du code, vous perdez tout cela.

Quelqu'un peut-il expliquer comment cette pratique de séparer les données du code a vu le jour et où elle va? Quelqu'un peut-il citer des publications de sommités ou fournir des données pertinentes qui démontrent un "code distinct des données" comme un commandement émergent et illustrent son origine?

1: si l'on peut même faire de telles distinctions. Je vous regarde, programmeurs Lisp.

Phil Frost
la source
5
N'hésitez pas à enterrer tous les fichiers html et css dans la langue de votre choix.
JeffO
3
Je pense que ce que l'auteur de la citation voulait dire, c'est que les nombres magiques ne sont pas vraiment immuables.
Pieter B
4
Il n'y a rien de mal à coder en dur les voyelles. Si votre application ne sera utilisée que pour compter les voyelles en anglais.
Michael Paulukonis
3
Une grande raison technique pour séparer le code et les données est de ne pas avoir à recompiler le code lorsque les données changent. Par conséquent, je me demande si cela s'applique dans la même mesure aux langages de script.
user16764
1
@MichaelPaulukonis: Et le mettre dans une base de données est une fausse solution. Des changements nécessaires pour le néerlandais? Zéro (pas même un changement de base de données). Changements nécessaires pour le français / allemand? Prise en charge d'au moins ISO-8859-1. (Plus que DB). Des changements sont-ils nécessaires pour le grec / russe? Prise en charge Unicode (plus que DB). En fait, je ne peux penser à aucune langue où cette base de données est d'une quelconque aide.
MSalters le

Réponses:

22

Il existe de nombreuses bonnes raisons de séparer les données du code, et certaines raisons de ne pas le faire. Les éléments suivants me viennent à l'esprit.

Opportunité. Quand la valeur des données est-elle connue? Est-ce au moment où le code est écrit, quand il est compilé, lié, libéré, autorisé, configuré, démarré l'exécution ou en cours d'exécution. Par exemple, le nombre de jours dans une semaine (7) est connu tôt, mais le taux de change USD / AUD sera connu assez tard.

Structure. S'agit-il d'un ensemble de temps de données unique en fonction d'une seule considération, ou pourrait-il être hérité ou faire partie d'une plus grande collection d'éléments? Des langages comme YAML et JSON permettent de combiner la valeur de plusieurs sources. Peut-être que certaines choses qui semblent initialement immuables sont mieux rendues accessibles en tant que propriétés dans un gestionnaire de configuration.

Localité. Si tous les éléments de données sont stockés dans un nombre limité d'emplacements, il est beaucoup plus facile de les gérer, en particulier si certains doivent être modifiés pour de nouvelles valeurs (immuables). La modification du code source uniquement pour modifier les valeurs des données présente le risque de modifications et de bogues involontaires.

Séparation des préoccupations. Il est préférable de séparer le bon fonctionnement des algorithmes de la prise en compte des valeurs de données à utiliser. Les données sont nécessaires pour tester les algorithmes et non pour en faire partie. Voir également http://c2.com/cgi/wiki?ZeroOneInfinityRule .

En réponse à votre question, ce n'est pas nouveau. Les principes fondamentaux n'ont pas changé depuis plus de 30 ans et ont fait l'objet d'écrits à plusieurs reprises au cours de cette période. Je ne me souviens d'aucune publication importante sur le sujet car il n'est généralement pas considéré comme controversé, juste quelque chose à expliquer aux nouveaux arrivants. Il y a un peu plus ici: http://c2.com/cgi/wiki?SeparationOfDataAndCode .

Mon expérience personnelle est que l'importance de cette séparation dans un logiciel particulier devient plus grande au fil du temps, pas moins. Les valeurs codées en dur sont déplacées dans les fichiers d'en-tête, les valeurs compilées sont déplacées dans les fichiers de configuration, les valeurs simples font partie des structures hiérarchiques et gérées.

En ce qui concerne les tendances, je n'ai pas vu de changements d'attitude majeurs chez les programmeurs professionnels (10 ans et plus), mais l'industrie est de plus en plus remplie de jeunes et beaucoup de choses que je pensais étaient connues et décidées continuent d'être mises au défi et réinventées, parfois hors de nouvelles idées mais parfois par ignorance.

david.pfx
la source
2
Pourriez-vous développer l'histoire et les tendances de cette pratique? Si tout le monde avait donné ces considérations, je n'aurais pas posé la question. La prémisse de la question est que les gens ne réfléchissent pas soigneusement à la destination de leurs données (constantes compilées, bases de données externes, YAML ...) mais pensent plutôt "CODE ET DONNÉES MIXTES MAUVAIS! HULK SMASH!" Pourquoi ou quand est-ce devenu une chose?
Phil Frost
Cela ne fait pas partie de mon expérience, donc je ne peux pas vous le dire. J'ai ajouté quelques paras à ma réponse.
david.pfx
Je pense que «l'afflux de jeunes» est une explication valable, mais je m'arrête d'accepter parce que j'aimerais entendre certains de ces jeunes pour voir d'où ils ont eu l'idée. De toute évidence, ils ont obtenu la partie «code et données séparés», mais je ne pense pas qu'ils aient obtenu le reste. L'ont-ils lu dans un article de blog? Un livre? Où et quand?
Phil Frost
Vous obtiendrez toujours "_____ MAUVAIS! HULK SMASH!" - cela ne veut pas dire que c'est vrai. Souvent, ce genre de choses (par exemple, "GOTO BAD! HULK SMASH!") Est enseigné aux débutants sans leur expliquer pourquoi ni quelles sont les exceptions.
AMADANON Inc.
Localityfonctionne également à l'envers: nous nous sommes retrouvés avec une sorte de système de type plugin en raison d'exigences personnalisées pour différents clients, et grâce à plusieurs années d'essais et d'erreurs, nous avons appris à garder leurs constantes (même des tableaux, au moyen de listes de dict)) de la base de données et dans le code. Les deux parce que son utilisation ailleurs que ce "plugin" est incorrect et parce que les modifications sont automatiquement versionnées lorsque des modifications se produisent.
Izkata
8

Les données évoluent beaucoup mieux et peuvent être interrogées et modifiées avec beaucoup plus de facilité lorsqu'elles sont séparées du code. Même si vos données sont de nature codée - par exemple, vos données représentent des règles ou des commandes - si vous pouvez stocker représenter ce code sous forme de données structurées, vous pouvez profiter des avantages du stockage séparé:

autorisations

Si les données sont codées en dur, vous devrez modifier le fichier source afin de modifier ces données. Cela signifie que soit:

  • Seuls les développeurs peuvent modifier les données. C'est mauvais - la saisie de données n'est pas quelque chose qui nécessite les compétences et les connaissances du développeur.

  • Les non-développeurs peuvent modifier le fichier source. C'est mauvais - ils pourraient visser le fichier source sans même le savoir!

  • Les données sont codées en dur dans des fichiers source distincts et les non-développeurs n'ont accès qu'à ces fichiers. Mais cela ne compte pas vraiment - maintenant les données sont séparées du code et stockées dans ses propres fichiers ...

édition

Donc, concernant qui peut modifier les données, il est préférable de les stocker séparément. Que diriez-vous de la façon dont ils modifieront les données? Si vous avez beaucoup de données, les taper à la main est fastidieux et source d'erreurs. Avoir une interface utilisateur pour cela est beaucoup mieux! Même si vous devez toujours tout taper, vous n'aurez pas à taper la plaque chauffante du format, donc il y a moins de chance que vous gâchiez le format et que vous fassiez le dossier entier!

Si les données sont codées en dur, la création de cette interface utilisateur signifie qu'un outil automatisé vous éditera les fichiers source manuscrits. Laissez cela pénétrer - un outil automatisé ouvrira vos fichiers source, tentera de trouver où les données devraient être et modifiera ce code. Brrr ... Microsoft a introduit des classes partielles en C # juste pour éviter ces choses ...

Si les données sont séparées, votre outil automatisé n'aura qu'à modifier les fichiers de données. Je préfère croire que les programmes informatiques éditant des fichiers de données ne sont pas si rares de nos jours ...

mise à l'échelle

Le code et les données évoluent très différemment. Au fur et à mesure que votre code se développe, vous souhaitez le séparer en plusieurs classes et méthodes (ou structures et fonctions de données), mais vos données - quelle que soit leur croissance - vous souhaitez les conserver au même endroit. Même si vous devez le séparer en plusieurs fichiers, vous souhaitez regrouper ces fichiers d'une manière ou d'une autre, il sera donc plus facile d'accéder à ces données à partir du code.

Imaginez donc que vous ayez des milliers de lignes de données dans un fichier source. Le compilateur / interprète doit parcourir toutes ces données à chaque fois qu'il lit le fichier et l'analyser avec son coûteux lexeur et analyseur - même si vous n'allez pas accéder à ces données dans cette exécution particulière du programme. De plus, lorsque vous modifiez le code réel dans ce fichier, vous devez faire le tour des données, ce qui alourdit tout le processus. De plus, les fichiers de données peuvent être indexés. Données codées en dur? Pas tellement...

recherche

Vous avez des tonnes de données - il est naturel que vous souhaitiez les parcourir.

  • Si vous le stockez dans une base de données - vous pouvez utiliser le langage de requête de base de données.

  • Si vous le stockez dans un fichier XML - vous pouvez utiliser XPath.

  • Si vous le stockez dans JSON / YAML - vous pouvez le charger dans le REPL de votre langage de script préféré et le rechercher.

  • Même si vous le stockez dans un ancien fichier texte, car il a une structure que votre programme peut reconnaître, vous pouvez utiliser grep / sed / awk pour le rechercher.

Bien qu'il soit vrai que vous pouvez également grep / sed / awk à travers des données codées en dur dans un fichier source, cela ne fonctionne pas aussi bien, car votre requête peut correspondre à d'autres lignes non liées ou manquer des lignes qui ont été écrites différemment parce que la syntaxe de représentation des données du langage de programmation le permet.

Il existe des outils pour rechercher dans le code, mais ils sont bons pour trouver des déclarations, pas des données codées en dur.

Cela étant dit...

Il est très important de faire la distinction entre les données et le code. Ce n'est pas parce qu'un élément est écrit sous forme de code qu'il ne peut pas s'agir de données. Et ce n'est pas parce qu'un élément est écrit avec une représentation de données qu'il ne s'agit pas, en fait, de code.

J'avais une classe quand nous avions des règles très strictes sur les "nombres magiques" - nous ne pouvions pas avoir de nombres dans notre code. Cela signifie que nous devions faire des choses comme:

#define THE_NUMBER_ZERO 0
//....
for(int i=THE_NUMBER_ZERO;i<cout;++i){
//....

ce qui est carrément ridicule! Oui, 0c'est techniquement des "données", mais cela fait tout aussi partie du code que le reste de la forboucle! Donc, même si nous pouvons le représenter sous forme de données et le séparer du code, cela ne signifie pas que nous devrions le faire . Pas parce que nous voulons laisser des données à l'intérieur du code, mais parce que ce n'est pas vraiment une donnée - pas plus que le reste du code, qui est également compilé en uns et en zéros ...

Idan Arye
la source
7

Je pense qu'il y a une certaine confusion. Vous mélangez deux choses ensemble: "Séparer le code et les données" et "exprimer le comportement du programme sous forme de données".

Dans votre cas, vous êtes réellement inquiet pour le second et pour y mélanger le premier. Lorsque vous exprimez le comportement d'un programme sous forme de données, il est plus facile à étendre. Dans votre exemple avec vowels = "aeiou", l'ajout d'une nouvelle voyelle est aussi simple que l'ajout d'un caractère. Si vous disposez de ces données en externe, vous pouvez modifier ce comportement sans avoir à recompiler le programme.

Et quand on y pense, la POO est le prolongement de cette réflexion. La liaison des données et du comportement ensemble vous permettra de modifier le comportement du programme en fonction des données du programme.

Euphorique
la source
2
Car naturellement, la liste des voyelles va changer.
cHao
13
@cHao Dès que i18n intervient, c'est le cas .
Rétablir Monica le
2
i18n peut vous casser la tête - voir quelques exemples pervers en Java dans javaspecialists.eu/archive/Issue209.html
Rory Hunter
2
@Angew: Dès que i18n intervient, vous êtes quand même foutu . Vous avez besoin de code pour cela; la solution naïve est incapable de traiter tous les cas, même en anglais. (Oubliez le ïpendant une seconde; parlons de yet w!) Le déplacement de la liste vers une base de données ne va pas résoudre ce problème, et est en fait nuisible - c'est une complexité qui ne vaudra pas si elle est mal faite, mais vous ne le ferez pas sait même ce « mauvais » est à moins que vous conceviez pour i18n à partir du sol. À ce stade, vous réalisez déjà qu'une liste de voyelles ne va tout simplement pas la couper de toute façon.
cHao
1
@BenLee: Je ne serais pas un peu surpris, en fait. Je travaille actuellement sur la modification d'un code comme celui-ci au moment où nous parlons. Mais l'externalisation de tout dans la base de données est révélatrice d'une toute autre sorte. Si vous ne savez pas déjà si quelque chose devra être modifié - et plus important encore, si vous ne savez pas encore comment il devra être modifié - alors OMI, il est préférable d'attendre jusqu'à ce que vous ayez besoin de cette flexibilité avant de l'ajouter. .
cHao
5

Par exemple, si la fonction de votre programme est de compter les voyelles, quel est le problème avec avoir voyelles = "aeiou" en elle?

Le stockage de la configuration en externe vous permet d'avoir une version du code qui devrait fonctionner avec de nombreuses configurations, l'alternative est de maintenir de nombreuses versions du logiciel qui ne diffèrent que par la configuration.

Vous mentionnez voyelles = "aeiou", et si je veux parfois "y", devrais-je avoir à reconstruire le programme entier? Puis-je facilement mettre à niveau les versions maintenant que j'ai modifié le code? S'il y a une erreur, est-ce que je l'ai provoquée ou le programme est-il cassé?

Si c'est à l'intérieur de votre programme, cela implique que votre programme ne s'attend pas à ce que les utilisateurs changent la définition des voyelles sans scanner le code pour voir les effets secondaires possibles. Si la définition est stockée en externe, cela implique que le programme ne doit pas s'arrêter pour une valeur raisonnable définie dans la configuration.

Lorsque vous séquestrez des données dans YAML ou des fichiers texte ou des bases de données stupides comme si vous supprimiez une tumeur du code

Certains le voient comme le contraire, c'est-à-dire que vous supprimez la tumeur du code de vos précieuses données, voir: la citation de Torvalds sur un bon programmeur

FMJaguar
la source
4
La citation de Torvalds fait référence aux structures de données, pas aux données.
user949300
L'OP déclare: "La programmation orientée objet a dit" nous voulons des structures de données arbitrairement riches ", et donc doté de structures de données avec des pouvoirs de code."
FMJaguar
1
Si vous apportez un changement fondamental à la définition de ce qu'est une voyelle, vous devrez au besoin réexécuter tous les tests automatisés. Les systèmes ont rarement, voire jamais, la possibilité de relancer les tests lorsqu'un fichier de configuration change sur un système déployé. De telles définitions doivent donc être intégrées au système; peut-être comme deux ensembles codés en dur avec une option de configuration pour choisir entre eux.
soru
+1 pour la citation de Torvalds. Je suis d'accord avec ce sentiment: dans l'exemple de la marionnette, je pense que le problème est que la marionnette n'a pas une bonne structure de données pour représenter les informations que les gens veulent y mettre. Plutôt que de réparer les structures de données, les développeurs de marionnettes ont affirmé que "les données dans le code" sont le problème (pourquoi? C'est la question!) Et ont développé hiera , que je considère comme un peu plus que de déplacer le problème ailleurs et de le rendre impossible pour associer le comportement aux données.
Phil Frost
2

J'étais sur un projet où le responsable a insisté pour mettre les données de référence dans de petites tables, et j'ai pensé que c'était idiot. Mais comme nous avions déjà mis en place notre infrastructure de persistance et notre connectivité, cela a fini par être un coût assez faible en plus des autres opérations de persistance que nous faisions.

Maintenant, je pense toujours que c'était une décision stupide, et si nous n'avions pas l'infrastructure à portée de main, je ne l'aurais pas fait.

Mais certains des arguments en faveur que je vois sont:

  • Si vous avez un état d'esprit de base de données, le fait de mettre des données de référence dans la base de données SQL vous permet de vous y joindre pour les rapports.
  • Si vous disposez d'un utilitaire d'administration ou d'un accès à la base de données, vous pouvez modifier les valeurs lors de l'exécution. (Bien que cela puisse jouer avec le feu.)

De plus, parfois, les politiques entravent les pratiques de codage. Par exemple, j'ai travaillé dans plusieurs magasins où pousser un fichier .xml est A-OK, alors que toucher une ligne dans le code nécessite un cycle de régression complet, et peut-être un test de charge. Donc, il y avait une équipe sur laquelle mes fichiers .xml pour le projet étaient extrêmement riches (et peut-être -heh- aurait pu contenir du code).

Je me demande toujours si je vais profiter de l'avantage de pousser des données hors du code dans un magasin de données externe, même si ce n'est qu'un fichier texte, mais j'ai travaillé avec des gens qui le voient comme ça comme leur premier impulsion.

Rob
la source
3
Bon commentaire sur les procédures de la boutique, où l'édition XML est "ok" mais l'édition de la même chose dans le code est un gros problème.
user949300
a travaillé dans un magasin où tout était dans la base de données qui pourrait être, jusqu'aux textes de l'écran. Mis à part le code de l'interface utilisateur, la seule chose qui ne se trouve pas dans la base de données était l'emplacement de la base de données et les informations d'identification ...
jwenting
3
cela semble toujours idiot jusqu'à ce qu'un jour, quelqu'un demande "pouvons-nous reconfigurer cela pour l'utilisateur X qui le demande", et puis cela ne semble pas si idiot après tout. Merde clients :)
gbjbaanb
2
... et si ce jour n'est "jamais", alors ça fait longtemps que je me sens bête
Rob
2

Permettez-moi de vous poser une contre-question tout à fait sérieuse: quelle est, selon vous, la différence entre "données" et "code"?

Quand j'entends le mot «données», je pense «état». Les données sont, par définition, la chose que l'application elle-même est conçue pour gérer, et donc la chose même que l'application ne peut jamais connaître au moment de la compilation. Il n'est pas possible de coder en dur les données, car dès que vous les codez en dur, cela devient un comportement - pas des données.

Le type de données varie selon l'application; un système de facturation commercial peut stocker des informations sur les clients et les commandes dans une base de données SQL, et un programme de graphiques vectoriels peut stocker des données de géométrie et des métadonnées dans un fichier binaire. Dans ces deux cas et tout le reste, il existe une séparation claire et incassable entre le code et les données. Les données appartiennent à l' utilisateur , pas au programmeur, donc elles ne peuvent jamais être codées en dur.

Ce dont vous semblez parler, c'est d'utiliser la description la plus précise techniquement disponible de mon vocabulaire actuel: des informations régissant le comportement du programme qui ne sont pas écrites dans le langage de programmation principal utilisé pour développer la majorité de l'application.

Même cette définition, qui est considérablement moins ambiguë que le seul mot «données», pose quelques problèmes. Par exemple, que se passe-t-il si des parties importantes du programme sont chacune écrites dans des langues différentes? J'ai personnellement travaillé sur plusieurs projets qui sont environ 50% C # et 50% JavaScript. Le code JavaScript est-il "données"? La plupart des gens diraient non. Qu'en est-il du HTML, est-ce que ces "données"? La plupart des gens diraient toujours non.

Et CSS? S'agit-il de données ou de code? Si nous considérons le code comme quelque chose qui contrôle le comportement du programme, alors le CSS n'est pas vraiment du code, car il affecte seulement (enfin, principalement) l'apparence, pas le comportement. Mais ce ne sont pas vraiment des données non plus; l'utilisateur ne le possède pas, l'application ne le possède même pas vraiment. C'est l'équivalent du code pour un concepteur d'interface utilisateur. C'est comme du code, mais pas tout à fait du code.

Je pourrais appeler CSS une sorte de configuration, mais une définition plus pratique est qu'il s'agit simplement de code dans un langage spécifique au domaine . C'est ce que représentent souvent votre XML, YAML et d'autres "fichiers formatés". Et la raison pour laquelle nous utilisons un langage spécifique au domaine est que, d'une manière générale, il est simultanément plus concis et plus expressif dans son domaine particulier que le codage des mêmes informations dans un langage de programmation à usage général comme C ou C # ou Java.

Reconnaissez-vous le format suivant?

{
    name: 'Jane Doe',
    age: 27,
    interests: ['cats', 'shoes']
}

Je suis sûr que la plupart des gens le font; c'est JSON . Et voici la chose intéressante à propos de JSON: en JavaScript, c'est clairement du code, et dans toutes les autres langues, ce sont des données clairement formatées. Presque tous les langages de programmation traditionnels ont au moins une bibliothèque pour "analyser" JSON.

Si nous utilisons exactement la même syntaxe à l'intérieur d'une fonction dans un fichier JavaScript, cela ne peut pas être autre chose que du code. Et pourtant, si nous prenons ce JSON, le poussons dans un .jsonfichier et l'analysons dans une application Java, tout à coup ce sont des «données». Est-ce vraiment logique?

Je soutiens que le "data-ness" ou "configuration-ness" ou "code-ness" est inhérent à ce qui est décrit, pas comment il est décrit.

Si votre programme a besoin d'un dictionnaire de 1 million de mots pour, par exemple, générer une phrase de passe aléatoire, voulez-vous le coder comme ceci:

var words = new List<string>();
words.Add("aa");
words.Add("aah");
words.Add("ahhed");
// snip 172836 more lines
words.Add("zyzzyva");
words.Add("zyzzyvas");

Ou voudriez-vous simplement insérer tous ces mots dans un fichier texte délimité par des lignes et dire à votre programme de le lire? Cela n'a pas vraiment d'importance si la liste de mots ne change jamais, ce n'est pas une question de savoir si vous codez en dur ou codez en douceur (que beaucoup considèrent à juste titre comme un anti-modèle lorsqu'il est appliqué de manière inappropriée), c'est simplement une question de quel format est le plus efficace et permet de décrire plus facilement le "truc", quel que soit le "truc". Ce n'est pas pertinent que vous l'appeliez code ou données; ce sont les informations dont votre programme a besoin pour fonctionner, et un format de fichier plat est le moyen le plus pratique pour le gérer et le maintenir.

En supposant que vous suiviez les bonnes pratiques, tout cela passe de toute façon dans le contrôle de code source, donc vous pourriez aussi bien l'appeler du code, juste du code dans un format différent et peut-être très minimaliste. Ou vous pouvez l'appeler configuration, mais la seule chose qui distingue vraiment le code de la configuration est de savoir si vous le documentez et dites aux utilisateurs finaux comment le modifier. Vous pourriez peut-être inventer un faux argument au sujet de l'interprétation de la configuration au moment du démarrage ou de l'exécution et non au moment de la compilation, mais alors vous commenceriez à décrire plusieurs langages à typage dynamique et presque certainement n'importe quoi avec un moteur de script intégré à l'intérieur (par exemple la plupart des jeux). Le code et la configuration sont ce que vous décidez de les étiqueter, rien de plus, rien de moins.

Désormais, il existe un danger d' externalisation d' informations qui ne sont pas réellement sûres à modifier (voir le lien "codage logiciel" ci-dessus). Si vous externalisez votre groupe de voyelles dans un fichier de configuration et le documentez en tant que fichier de configuration à vos utilisateurs finaux, vous leur donnez un moyen presque infaillible de casser instantanément votre application, par exemple en mettant "q" comme voyelle. Mais ce n'est pas un problème fondamental avec la "séparation du code et des données", c'est tout simplement un mauvais sens du design.

Ce que je dis aux développeurs juniors, c'est qu'ils devraient toujours externaliser les paramètres qu'ils s'attendent à changer par environnement. Cela inclut des éléments tels que les chaînes de connexion, les noms d'utilisateur, les clés d'API, les chemins de répertoire, etc. Ils peuvent être les mêmes sur votre boîte de développement et en production, mais probablement pas, et les administrateurs système décideront à quoi ils veulent ressembler en production, pas les développeurs. Vous avez donc besoin d'un moyen d'appliquer un groupe de paramètres sur certaines machines et d'autres paramètres sur d'autres machines - ergo, fichiers de configuration externes (ou paramètres dans une base de données, etc.)

Mais j'insiste sur le fait que le simple fait de mettre des "données" dans un "fichier" n'est pas la même chose que de l'externaliser en tant que configuration. Mettre un dictionnaire de mots dans un fichier texte ne signifie pas que vous voulez que les utilisateurs (ou l'informatique) le changent, c'est juste un moyen de permettre aux développeurs de comprendre plus facilement ce qui se passe et, si nécessaire, de faire changements occasionnels. De même, le fait de placer les mêmes informations dans une table de base de données ne compte pas nécessairement comme une externalisation du comportement, si la table est en lecture seule et / ou les administrateurs de base de données sont invités à ne jamais se tromper avec. La configuration implique que les données sont modifiables, mais en réalité cela est déterminé par le processus et les responsabilités plutôt que par le choix du format.

Donc, pour résumer:

  • "Code" n'est pas un terme défini de manière rigide. Si vous développez votre définition pour inclure des langages spécifiques au domaine et tout ce qui affecte le comportement, une grande partie de cette friction apparente disparaîtra tout simplement et tout cela aura du sens. Vous pouvez avoir un "code" DSL non compilé dans un fichier plat.

  • Les «données» impliquent des informations qui appartiennent à l'utilisateur ou à au moins une personne autre que les développeurs et qui ne sont généralement pas disponibles au moment de la conception. Il ne pouvait pas être codé en dur, même si vous le vouliez. À l'exception possible du code auto-modifiable , la séparation entre le code et les données est une question de définition et non de préférence personnelle.

  • Le "codage logiciel" peut être une pratique terrible lorsqu'il est sur-appliqué, mais toutes les instances d'externalisation ne constituent pas nécessairement un codage logiciel, et de nombreuses instances de stockage d'informations dans des "fichiers plats" ne sont pas nécessairement une tentative d'externalisation de bonne foi.

  • La configuration est un type spécial de codage logiciel qui est nécessaire en raison de la connaissance que l'application peut avoir besoin de s'exécuter dans différents environnements. Le déploiement d'un fichier de configuration séparé avec l'application est beaucoup moins de travail (et beaucoup moins dangereux) que le déploiement d'une version différente du code dans chaque environnement. Ainsi , certains types de codage doux sont réellement utiles.

Aaronaught
la source
1

Je suggère de lire cet article classique d'Oren Eini (alias Ayende Rahien)

http://ayende.com/blog/3545/enabling-change-by-hard-coding-everything-the-smart-way

Ma propre conclusion est de me concentrer sur la simplicité et la lisibilité. Cela peut signifier qu'il est préférable de laisser les choses qui sont peu susceptibles d'être reconfigurées codées en dur (lisibles). Cela vous permet d'utiliser la syntaxe complète d'un langage de programmation pour exprimer les paramètres, ainsi que d'obtenir des effets secondaires bénéfiques comme la complétion de code et les erreurs de compilation en cas de mauvaise utilisation.

De cette façon, vous évitez potentiellement la complexité de l'analyse / interprétation («mais quelqu'un d'autre analyse mon YAML / JSON» - le mappage du texte analysé dans les appels API spécifiques peut être une forme d'interprétation), et évitez la complexité d'une autre étape entre les «données "et son utilisation.

Certains cas se prêtent à être exprimés en données même dans un scénario comme celui-ci: par exemple, la spécification de milliers de points dans l'espace 3D peut être mieux adaptée à un fichier texte que le code, bien que dans certaines langues, y compris C à l'aide d'initialiseurs struct, code peut être approprié même pour cela.

orip
la source
1

Ok, supposons que vous vouliez écrire une sorte de programme c ++ pour vos loisirs. Vous savez exactement ce qu'il doit faire et ce qu'il n'aura jamais besoin de faire. Prenez maintenant n'importe quel livre sur la «conception de logiciels modernes». Voici la règle du jeu: pour chaque classe de votre projet et pour chaque cas si petit, vous devez implémenter chaque motif fantaisie décrit dans ce livre afin de faire de votre code un "design épuré". Eh bien, "l'injection de dépendance" sera suffisante pour beaucoup de personnes, je suppose. (C'est du c ++, pas du java!) La programmation est enseignée d'un point de vue de plus en plus théorique. Il ne suffit pas de faire le travail, vous devez écrire du code qui est maintenable, imbécile prouver ... tout va bien. Le problème commence lorsque ppl. arrêtez de penser à la raison réelle, les modèles de conception ont été inventés et deviennent dogmatiques.

Permettez-moi de vous empêcher d'écrire votre outil de comptage de lettres en (sur) utilisant un seul principe de conception simple: lorsque vous écrivez du code qui effectue un certain travail sur les données d'entrée d'un certain type, assurez-vous qu'il est capable d'effectuer cette tâche pour n'importe quelle entrée donnée des données de ce type. - Lorsque vous voulez écrire un outil de comptage de lettres, il est clairement logique de l'écrire de manière à ce qu'il puisse non seulement compter les voyelles, mais «n'importe quelle lettre». - Puisque vous ne savez peut-être pas en quoi consiste le corpus que vous analysez, vous pouvez également choisir un encodage très général (UTF-16) et couvrir la plupart (toutes?) Les langues écrites et leurs symboles.

Jusque-là, nous avons une fonction avec deux arguments (le corpus et les lettres à compter). Nous ne cherchons qu'à trouver un "type" ou une "classe" raisonnablement généraux auxquels les lettres appartiennent aussi: nous pouvons certainement faire mieux que les symboles ASCII!

Entrez un démon brandissant le dogme "généralisation et réutilisabilité": - Pourquoi ne pas compter un symbole d'une classe dans un flux d'entrée de cette classe? (résumé des lettres aux séquences de bits de longueur arbitraire mais finie car c'est la plus générale que vous pouvez obtenir avec un ordinateur ...) - Attendez, même alors, nous comptons toujours en nombres naturels. Cependant, le comptage peut être généralisé comme un mappage d'un ensemble dénombrable à lui-même remplissant les axiomes ... [vous avez l'idée]

Maintenant, cet exemple peut être idiot, mais si vous envisagez des tâches de conception plus complexes qu'un outil de comptage, vous trouverez peut-être toutes les opportunités d'introduire l'abstraction supplémentaire requise en fonction d'une sorte de modèle de conception que vous avez trouvé dans votre livre.

La séparation des "données" et du "code" sera probablement triviale (arguments de fonction) ou vous vous retrouverez à traiter des invariants comme variables ("données").

En cas de confusion, il est probable que les "interfaces" et les "services" et toutes les spécificités de classe (par exemple les types) soient soudainement des "données", c'est-à-dire des dépendances à injecter de l'extérieur. Je pense que les cours d'informatique dispensés à l'université sont devenus un peu comme des cours de philosophie et il y a moins de temps pour de vrais projets afin que les étudiants puissent acquérir une expérience sur la façon de créer des logiciels qui fonctionnent. Si vous vous demandez pourquoi vous devez utiliser un modèle incroyablement complexe au lieu d'une solution évidente, ce développement est (probablement) comment cette exigence a été "créée" ...

Pour votre problème spécifique: Si vous pouviez 1.) écrire un programme avec un maximum de codage en dur pour votre cas spécifique, puis 2.) généraliser à partir de ce code d'une manière simple par exemple. en introduisant plus d'arguments de fonction et en utilisant d'autres "modèles triviaux", vous pouvez être sûr de séparer le code et les données, de la manière évidente, comme cela a été fait depuis que la programmation fonctionnelle a été inventée. (ofc vous sautez 1. et faites 2. instantanément ...)

Tout ce qui n'est pas évident ici est probablement un cas de "blocage théorique": comme écrire une interface se référant à une interface et encore une autre interface ... et à la fin vous avez un petit fichier xml soigné afin de configurer toutes ces interfaces et les dépendances à injecter dans votre encombrement d'interface de classe.

Espérons simplement que l'analyseur xml dont vous avez besoin n'a pas besoin d'une configuration xml pour fonctionner ...

bhak
la source