web-dev-qa-db-fra.com

Stratégie de transmission des arguments - variables d'environnement et ligne de commande

La plupart des applications que nous développons doivent être paramétrées en externe au démarrage. Nous transmettons les chemins de fichiers, les noms de canaux, les adresses TCP/IP, etc. Jusqu'à présent, j'ai utilisé la ligne de commande pour les transmettre à l'application en cours de lancement. J'ai dû analyser la ligne de commande dans main et diriger les arguments là où ils sont nécessaires, ce qui est bien sûr un bon design, mais est difficile à maintenir pour un grand nombre d'arguments. Récemment, j'ai décidé d'utiliser le mécanisme des variables d'environnement . Ils sont globaux et accessibles de partout, ce qui est moins élégant du point de vue architectural, mais limite la quantité de code.

Ce sont mes premières impressions (et peut-être assez superficielles) sur les deux stratégies, mais j'aimerais entendre les opinions de développeurs plus expérimentés - Quels sont les hauts et les bas de l'utilisation des variables d'environnement et de la ligne de commande des arguments pour passer des arguments à un processus? Je voudrais prendre en compte les points suivants:

  1. qualité de conception (flexibilité/maintenabilité),
  2. contraintes de mémoire,
  3. portabilité de la solution.

Remarques:

Un d. 1. C'est l'aspect principal qui m'intéresse.

Un d. 2. C'est un peu pragmatique. Je connais certaines limitations sur Windows qui sont actuellement énorme (plus de 32 Ko pour la ligne de commande et le bloc d'environnement). Je suppose que ce n'est pas un problème, car vous devez simplement utiliser un fichier pour passer des tonnes d'arguments si vous en avez besoin.

Un d. 3. Je ne connais presque rien d'Unix, donc je ne sais pas si les deux stratégies sont aussi utilisables que sous Windows. Développez cela si vous le souhaitez.

73
Janusz Lenar

1) Je recommanderais d'éviter autant que possible les variables environnementales.

Avantages des variables environnementales

  • facile à utiliser car ils sont visibles de partout. Si de nombreux programmes indépendants ont besoin d'informations, cette approche est beaucoup plus pratique.

Inconvénients des variables environnementales

  • difficile à utiliser correctement car ils sont visibles (supprimables, réglables) de n'importe où. Si j'installe un nouveau programme qui s'appuie sur des variables environnementales, vont-ils piétiner mes programmes existants? Ai-je par inadvertance bousillé mes variables environnementales lorsque je faisais du singe hier?

Mon avis

  • utilisez des arguments de ligne de commande pour les arguments qui sont les plus susceptibles d'être différents pour chaque invocation individuelle du programme (c'est-à-dire n pour un programme qui calcule n!)
  • utiliser des fichiers de configuration pour les arguments qu'un utilisateur peut raisonnablement vouloir changer, mais pas très souvent (c'est-à-dire afficher la taille lorsque la fenêtre s'ouvre)
  • utiliser les variables d'environnement avec parcimonie - de préférence uniquement pour les arguments qui ne devraient pas changer (c'est-à-dire l'emplacement de l'interpréteur Python)
  • votre point They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of code me rappelle les justifications de l'utilisation des variables globales;)

Mes cicatrices après avoir vécu les horreurs de la surutilisation des variables environnementales

  • deux programmes dont nous avons besoin au travail, qui ne peuvent pas fonctionner sur le même ordinateur en même temps en raison de conflits environnementaux
  • plusieurs versions de programmes portant le même nom mais des bogues différents - ont mis un atelier entier à genoux pendant des heures car l'emplacement du programme a été retiré de l'environnement et était (silencieusement, subtilement) faux.

2) Limites

Si je repoussais les limites de ce que la ligne de commande peut contenir ou de ce que l'environnement peut gérer, je refactoriserais immédiatement.

J'ai utilisé JSON dans le passé pour une application en ligne de commande qui nécessitait beaucoup de paramètres. C'était très pratique de pouvoir utiliser des dictionnaires et des listes, ainsi que des chaînes et des nombres. L'application n'a pris que quelques arguments de ligne de commande, dont l'un était l'emplacement du fichier JSON.

Avantages de cette approche

  • n'a pas eu à écrire beaucoup de code (pénible) pour interagir avec une bibliothèque CLI - il peut être difficile d'obtenir de nombreuses bibliothèques communes pour appliquer des contraintes compliquées (par `` compliqué '', je veux dire plus complexe que de rechercher un clé spécifique ou alternance entre un jeu de clés)
  • ne vous souciez pas des exigences des bibliothèques CLI pour l'ordre des arguments - utilisez simplement un objet JSON!
  • facile à représenter des données compliquées (répondre What won't fit into command line parameters?) comme les listes
  • facile à utiliser les données d'autres applications - à la fois pour créer et pour analyser par programme
  • facile à accueillir les futures extensions

Note: Je veux distinguer cela de l'approche du fichier .config - ce n'est pas pour stocker la configuration utilisateur. Je devrais peut-être appeler cela l'approche du "fichier de paramètres de ligne de commande", car je l'utilise pour un programme qui a besoin de beaucoup de valeurs qui ne correspondent pas bien à la ligne de commande.


3) Portabilité de la solution: je ne connais pas grand-chose aux différences entre Mac, PC et Linux en ce qui concerne les variables d'environnement et les arguments de ligne de commande, mais je peux vous dire:

  • les trois prennent en charge les variables environnementales
  • ils prennent tous en charge les arguments de ligne de commande

Oui, je sais - ce n'était pas très utile. Je suis désolé. Mais le point clé est que vous pouvez attendez-vous à ce qu'une solution raisonnable soit portable, bien que vous souhaitiez certainement le vérifier pour vos programmes (par exemple, les arguments de ligne de commande sont-ils sensibles à la casse sur toutes les plates-formes? Sur tous je ne sais pas).


Un dernier point:

Comme Tomasz l'a mentionné, peu importe la plupart des applications d'où proviennent les paramètres.

66
Matt Fenwick

Vous devez résumer les paramètres de lecture en utilisant le modèle Strategy . Créez une abstraction nommée ConfigurationSource ayant la méthode readConfig(key) -> value (ou renvoyant un objet/une structure Configuration) avec les implémentations suivantes:

  • CommandLineConfigurationSource
  • EnvironmentVariableConfigurationSource
  • WindowsFileConfigurationSource - chargement depuis un fichier de configuration depuis C:/Document and settings...
  • WindowsRegistryConfigurationSource
  • NetworkConfigrationSource
  • UnixFileConfigurationSource - - chargement depuis un fichier de configuration depuis /home/user/...
  • DefaultConfigurationSource - valeurs par défaut
  • ...

Vous pouvez également utiliser Chaîne de responsabilité modèle pour chaîner les sources dans diverses configurations comme: si l'argument de ligne de commande n'est pas fourni, essayez la variable d'environnement et si tout le reste échoue, retournez les valeurs par défaut.

Annonce 1. Cette approche vous permet non seulement d'abstraire la configuration de lecture, mais vous pouvez facilement changer le mécanisme sous-jacent sans aucun effet sur le code client. Vous pouvez également utiliser plusieurs sources à la fois, en reculant ou en rassemblant la configuration à partir de différentes sources.

Annonce 2. Choisissez simplement la mise en œuvre appropriée. Bien sûr, certaines entrées de configuration ne rentrent pas par exemple dans les arguments de ligne de commande.

Annonce 3. Si certaines implémentations ne sont pas portables, en avoir deux, une ignorée/ignorée silencieusement lorsqu'elle ne convient pas à un système donné.

6
Tomasz Nurkiewicz

Je pense que cette question a déjà été assez bien répondu, mais j'ai l'impression qu'elle mérite une mise à jour 2018. Je pense qu'un avantage non mentionné des variables environnementales est qu'elles nécessitent généralement moins de code de plaque de chaudière pour fonctionner. Cela rend le code plus lisible et plus propre. Cependant, un inconvénient majeur est qu'ils suppriment des couches d'isolement des différentes applications s'exécutant sur la même machine. Je pense que c'est là que Docker brille vraiment. Mon modèle de conception préféré consiste à utiliser exclusivement des variables d'environnement et à exécuter l'application à l'intérieur d'un conteneur Docker. Cela supprime le problème d'isolement.

3
mdornfe1